【问题标题】:How to filter query from Firebase?如何过滤来自 Firebase 的查询?
【发布时间】:2019-02-22 08:39:01
【问题描述】:

我在 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 匹配。

在其他查询中,我使用了这样的内容:

firebaseDatabase.child("users").orderByChild("location").equalsTo(<cityID>)

当孩子 location 不是“数组”时,这非常有效。

那么有什么办法吗?

或者我只需要把所有社区都带上,然后在设备中过滤?

【问题讨论】:

    标签: java android firebase firebase-realtime-database


    【解决方案1】:

    我只需要获取他们拥有的城市列表中的社区,并与特定的 locationID 匹配

    很遗憾,您无法使用实际的数据库结构来实现这一点。

    当子位置不是“数组”时,这非常有效。

    当位置是 String 类型的属性而不是数组时,它可以工作,因为您可以传递给 equalsTo() 方法的对象的类型是 String 类型而不是数组。

    那么有什么办法吗?

    要解决此问题,您应该复制数据。这种做法称为denormalization,是 Firebase 的常见做法。如果您是 NoSQL 数据库的新手,我建议您观看此视频,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 实时数据库。

    或者我只需要把所有社区都带上,然后在设备中过滤?

    没有必要这样做。使用此解决方案,您只会获得所需的元素。

    【讨论】:

      【解决方案2】:

      我假设您使用的是 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 不支持...跨多个集合或子集合的单个查询。每个查询都针对单个文档集合运行。有关数据结构如何影响查询的详细信息,请参阅选择数据结构。

      因此,如果根据城市属性查询社区非常重要,请考虑重组数据库或将所有社区带入并按照您所说的过滤后。最好重组数据库,因为这可能会影响您的应用程序性能。

      【讨论】:

      • 其实我忘记放了,不是Firestore(以后会迁移)是RealtimeDatabase。但我记下了你写给未来的代码。
      • OP 正在寻找有关 Firebase 实时数据库和 not Cloud Firestore 的答案,后者是一个完全不同的产品。即使是 Firestore,这个答案也不起作用,因为那些 cities 是映射而不是数组。
      猜你喜欢
      • 1970-01-01
      • 2019-11-04
      • 2012-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-05
      • 1970-01-01
      相关资源
      最近更新 更多