使用 OR 查询获取 Firestore 文档

Posted

技术标签:

【中文标题】使用 OR 查询获取 Firestore 文档【英文标题】:Get Firestore document with OR query 【发布时间】:2021-07-19 11:22:00 【问题描述】:

我正在使用 Firestore 为使用 Swift 的 ios 应用存储好友列表。

我的friends 集合中的每个文档都有一个sendertargetaccepted 字段

当用户打开他们的朋友列表时,我需要该应用程序检索他们的用户 ID 在 targetsender 字段中的每个文档,并且仅在 accepted == true 字段中进行检索

我知道我可以链接 .where() 函数来创建 AND 查询。

但据我所知,无法使用 Firestore 进行 OR 查询。

有没有办法在一个查询中做到这一点?

谢谢

编辑

这是数据库结构的快照

每个文档都是在发送好友请求时创建的,然后在需要时用于为两个用户构建好友列表(而不是存储 2 个用户 ID 数组,每次更改都必须单独更新)

【问题讨论】:

请分享您的数据库结构的屏幕截图,然后说明您要查找哪些字段? 我对我的问题进行了一些小改动以使其更清晰一些,但您所要求的一切都已在问题@Dharmaraj 中提供 文档结构我还不清楚。 accepted 字段是数组还是映射?您是否存储了作为用户朋友的用户 ID 数组?一个示例屏幕截图真的很有帮助 虽然@frankvanpuffelen 显示没有直接的“或”样式查询,但您通常可以利用数组来提供类似的功能。我用一个查询解决了这个问题的代码抛出了一个答案(每个 Franks 的答案) 【参考方案1】:

我需要该应用检索其用户 ID 在目标或发件人字段中的每个文档

这是不可能的,因为 Firestore 不允许字段之间的 OR 条件。

你能得到的最接近的方法是在文档中添加一个数组字段,在其中保存所有参与者的 UID,然后使用 in 操作 checking whether the UID you're looking for is in that array:

friendsRef
  .whereField("participants", arrayContains: "uidOfUser")

【讨论】:

拍摄,我希望避免在朋友连接发生变化时必须更新的大量字符串列表:/ .... 这让谷歌不认为 OR 查询足够重要的原因令人难以置信包括在他们的 API 0.o 谢谢 :) 所以考虑到这一点,在每个用户文档中都有一个 friends 数组字段会更有效,还是保留我开始的内容(参见上面的新屏幕截图)并运行 2 个查询(每个字段一个)....前一个选项(在我看来)似乎更容易出错 “这令人难以置信,为什么 google 不认为 OR 查询很重要” Firestore 只允许满足其性能保证的查询,即查询性能不依赖于文档数量那些是查询,并且仅基于实际返回的数据量。对于跨多个字段的 OR,它无法满足此保证。【参考方案2】:

请参阅 Franks 的正确答案,使用数组稍微跳出框框提出了一个解决方案。我想展示我们用来处理这些案例的结构(基于 Franks 的回答)

Firebase 可以检查数组中的值,因此只需更改结构即可进行“或”样式查询。这是一些示例数据

friends
   doc_0
      accepted: true
      requests //an array
         0: uid_0
         1: uid_2
   doc_1
      accepted: true
      requests
         0: uid_6
         1: uid_0
   doc_2
      accepted: true
      requests
         0: uid_1
         1: uid_6

请记住,在这种结构中,数组元素 0 是“发送者”,数组元素 1 是“目标”

在这种情况下,假设用户 0 (uid_0) 想要其用户 uid (uid_0) 位于“发件人”或“目标”位置(即 doc_0 或 doc_1)的所有文档。这是代码

func getRequests() 
    let friendsCollection = self.db.collection("friends") //self.db points to my firebase
    let query = friendsCollection.whereField("accepted", isEqualTo: true)
                                 .whereField("requests", arrayContains: "uid_0")
    query.getDocuments(completion:  snapshot, error in
        if let err = error 
            print(err.localizedDescription)
            return
        

        guard let docs = snapshot?.documents else  return 

        for doc in docs 
            let docId = doc.documentID
            print(docId)
        
    )

结果

doc_0
doc_1

【讨论】:

以上是关于使用 OR 查询获取 Firestore 文档的主要内容,如果未能解决你的问题,请参考以下文章

Firestore - 如何在不真正获取所有文档的情况下找到可以使用查询获取的文档数量? [复制]

使用 FirestoreRecyclerAdapter 时如何获取 Firestore 文档 ID?

我可以获取从 Firestore 集合组查询中获取的文档的路径或引用吗?

FLUTTER FIRESTORE - 查询字段并获取文档 ID 并检查其他字段

Firestore:如何在集合中获取随机文档

如何通过在 Firestore 中的查询从索引中获取多个文档到其他索引