【问题标题】:Firebase Firestore - OR queryFirebase Firestore - OR 查询
【发布时间】:2018-03-25 09:34:00
【问题描述】:

如何通过一个字段的多个值获取数据?例如,我有一个包含帖子的数据库,我想查询 blogId 为 1 或 2 的所有帖子,按时间戳排序。

collection("posts").whereEqualTo("blogId", "1")
.whereEqualTo("blogId", 2).orderBy("timestamp", Query.Direction.DESCENDING).limit(50)

上面的代码不起作用:(

如何做到这一点? 问候:)

【问题讨论】:

标签: android google-cloud-firestore


【解决方案1】:

Firestore now supports "IN" queries 用于此目的。

查询如下所示:

database.collection("collectionName").where("fieldName", "in", ["fieldValue1", "fieldValue2"]);

您最多可以有 10 个值 (fieldValueX) 来检查“IN”。


所需的代码 OP 如下:

database.collection("posts").where("blogId", "in", ["1", "2"]); 

【讨论】:

  • 多个字段呢?
  • @IsraelObanijesu 据我了解,您必须为此使用复合查询,但值得检查 firebase 文档以确保。我不太会处理这样的查询
  • 很好的答案,尽管这在 Firebase 方面的实现非常糟糕,并且严格限制了 10 个值...
【解决方案2】:

你可以合并 Observables 并作为一个返回

orQuery(){

    const $one = this.afs.collection("posts", ref => ref.where("blogId","==","1")).valueChanges();
    const $two = this.afs.collection("posts", ref => ref.where("blogId","==","2")).valueChanges();

    return combineLatest($one,$two).pipe(
        map(([one, two]) => [...one, ...two])
    )
}

getOr(){
    this.orQuery().subscribe(data => console.log(data))
}

【讨论】:

  • 请注意,在这种方法中,最终结果可能包含重复项,具体取决于查询(在这种确切情况下,不会有重复项,因为相同的字段用于具有不同值的查询)。
  • 如果我们使用多个字段(例如您的答案)对数据进行分页,可能会很困难。
【解决方案3】:

Firebase 已听取了我们的请求,其中包含来自 7 Nov, 2019IN 查询。这是一种OR 查询,您最多可以有10 OR 过滤器。

对于安卓:

collection("posts").whereIn("blogId", Arrays.asList("1", "2"))
.orderBy("timestamp", Query.Direction.DESCENDING).limit(50);

Firebase documentation

【讨论】:

  • 应该是正确答案
【解决方案4】:

OR 运算符在 firebase firestore 中不被接受:

Cloud Firestore 对逻辑 OR 查询提供有限的支持。 in 和 array-contains-any 运算符支持单个字段上最多 10 个相等 (==) 或数组包含条件的逻辑 OR。对于其他情况,请为每个 OR 条件创建单独的查询,并在您的应用中合并查询结果。

Queries in Cloud Firestore, Query limitations

通常使用 firebase 语法,您可以调用两个集合:

const res1 = async collection("posts", ref => ref.where('blogId', '==', 1).get();
const res2 = async collection("posts", ref => ref.where('blogId', '==', 2).get();

您可以在提供给视图之前合并结果。

但在这种情况下,如果您有 blogId,您可以使用以下语法: collection("posts").orderBy('blogId').startAt(1).endAt(2);

e.d

【讨论】:

    【解决方案5】:

    我找不到任何关于 OR 条件的文档。但是您可以将您对blogId 的要求改写如下:

    WHERE blogId > 0 AND blogId < 3
    

    试试这个代码:

    collection("posts")
    .where("blogId", ">", "0")
    .where("blogId", "<", "3")
    .orderBy("timestamp", Query.Direction.DESCENDING)
    .limit(50)
    

    【讨论】:

    • 是的,但我的情况稍微复杂一些。我有一个应用程序,用户可以在其中订阅一些博客。所以我需要检索几个 id 的所有最新帖子(它可以是 2,5 或更多 id)。 id 是自动生成的(例如 wordpress - 831cacax613das)或来自博主(对于 blogspot 博客 - 12320183127312307212)。我目前正在使用带有 elasticsearch 的 firebase 数据库,但我有兴趣迁移到 Firestore。
    • 在此处查看如何使用集合:cloud.google.com/firestore/docs/solutions/arrays
    • 嗯,我可以使用单个元素映射存储 blogId 并像示例中一样查询它,但在这种情况下,每个 blogId 都需要单独的索引。目前我的数据库中有 300 个博客,但如果我有几千个呢? :D 即使我将使用整数值而不是布尔值将其存储在地图中,我也只能使用一个字段进行查询,因此无法调用它: .whereGreaterThan("blogIdMap.kqy04zya72zit5x7n9", 0) .whereGreaterThan("blogIdMap.kqy0n2dt2maqluvi3eu ", 10)
    • 是的,这似乎是个问题。你能加入一个有这些 ID 的表吗?
    • 不,目前我将 blogId 作为普通字段 (blogId = 123131) 存储在帖子实体中。但是,用户有订阅博客的地图(123131 = true)。我正在考虑将查询可观察对象合并为一个,但这不是一个好主意,因为我想获得 f.e. 10 个最新帖子。而且我会失去分页能力。
    【解决方案6】:

    Firestore 没有 OR 查询。他们这样做的方式是运行两个查询并将它们拼接起来。

    你可以例如:

    const search = ( key, value ) =>  collection( 'users' ).where( key, '==', value ).get().then( doc => doc.data() )
    
    Promise.all( [ search( 'name', 'John' ), search( 'name', 'Johnny' ) ] )
    .then( ( [ one, two ] ) => one.concat( two ) )
    .then( allResults => dothings() )
    

    【讨论】:

      【解决方案7】:

      对于 Android,我正在使用这样的 OR 查询。

      List<String> values = new ArrayList<>();
          values.add("Value 1");
          values.add("Value 2");
      

      然后像这样使用 .whereIn 查询。

      db.collection("collectionName")
                  .whereIn("fieldName", values)   // where values is the list we created
                  .get()
                  .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                      @Override
                      public void onComplete(@NonNull Task<QuerySnapshot> task) {
      
                          if (task.isSuccessful()) {
      
                            // Do your stuff
      
                          }
      
                      }
                  });
      

      【讨论】:

        【解决方案8】:

        试试这个

        collection("posts").start("blogId", "1")
        .end("blogId", 2).orderBy("timestamp", Query.Direction.DESCENDING).limit(50)
        

        【讨论】:

          【解决方案9】:

          您可以使用De Morgaan's 法则将AND 查询重写为OR 查询。

          【讨论】:

          • 它仍然是两个quieres。
          • 我可能弄错了,但这适用于XOR 而不是OR 对吗?
          • 你错了?
          猜你喜欢
          • 1970-01-01
          • 2018-04-11
          • 2018-03-30
          • 2021-04-27
          相关资源
          最近更新 更多