我在Firebase中有一个结构,例如:(数据库为Realtime Database
)。
community
|--<communityID>
|--cities
| |--<locationID>:boolean
| |--<locationID>:boolean
| |--<locationID>:boolean
|--name
|--users
|-- ...
|--<communityID>
|--cities
| |--<locationID>:boolean
| |--<locationID>:boolean
| |--<locationID>:boolean
|--name
|--users
|-- ...
与其他许多字段一样。
我只需要获取它们在cities
列表中与特定locationID
匹配的社区。 p>
在其他查询中,我使用了类似的方法:
firebaseDatabase.child("users").orderByChild("location").equalsTo(<cityID>)
当孩子location
不是“数组”时,这种方法很完美。
那么有什么办法可以做到?
或者我只需要带入所有社区,然后在设备中进行过滤?
答案 0 :(得分:2)
我只需要获取他们在城市列表中拥有的社区,并与特定的locationID匹配
不幸的是,您无法使用实际的数据库结构来实现这一目标。
当子位置不是“数组”时,这很完美。
当位置是String类型的属性而不是数组时,它可以工作,因为可以传递给equalsTo()
方法的对象的类型是String类型,而不是数组。
那么有什么办法吗?
要解决这个问题,您应该复制数据。这种做法称为denormalization
,是Firebase的常见做法。如果您不熟悉NoQSL数据库,建议您观看此视频Denormalization is normal with the Firebase Database,以更好地理解。
此外,在复制数据时,需要记住一件事。用与添加数据相同的方式,您需要对其进行维护。换句话说,如果您想更新/删除项目,则需要在它存在的每个位置进行。
也就是说,在您的特定情况下,您应该考虑通过创建另一个名为comunityCities
的节点来扩展数据结构以允许反向查找,在该节点中应将所有对应的社区添加为对象。因此,您的数据库结构应类似于此:
Firebase-root
|
--- comunityCities
|
--- locationID
|
--- communityID
| |
| --- //Community details
|
--- communityID
|
--- //Community details
使用此架构,您只需使用以下代码行即可查询数据库以获取与单个位置对应的所有社区:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference comunityCitiesRef = rootRef.child("comunityCities");
comunityCitiesRef.addListenerForSingleValueEvent(/* ... */);
您可以从以下帖子中的答案中了解更多信息:
这是Cloud Firestore问题的答案,但是对于Firebase实时数据库,同样的规则适用。
或者我只需要带入所有社区,然后在设备中进行过滤?
没有必要。使用此解决方案,您只会得到所需的元素。
答案 1 :(得分:0)
我假设您正在使用Friebase Firestore(而不是实时数据库)。 检查以下内容:https://firebase.google.com/docs/firestore/query-data/queries
有一个名为“ array_contains”的比较。 因为kotlin应该是
之类的函数val communityRef = db.collection("communityID")
val query = communityRef.whereArrayContains("cities", <locationID>)
在这种情况下,这足够了。
顺便说一句,如果您在页面末尾看到“限制”字样
Cloud Firestore不支持...跨多个集合或子集合的单个查询。每个查询针对单个文档集合运行。有关数据结构如何影响查询的更多信息,请参阅选择数据结构。
因此,如果根据城市属性查询社区非常重要,请考虑重组数据库,或者将所有社区带入数据库,然后按照您所说的进行过滤。最好重组数据库,因为这可能会影响您的应用程序性能。