【问题标题】:Get Firestore document with OR query使用 OR 查询获取 Firestore 文档
【发布时间】: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 的答案)

标签: swift firebase google-cloud-firestore


【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-22
    • 2020-01-05
    • 1970-01-01
    • 2021-04-27
    相关资源
    最近更新 更多