Firestore查询数组不含用户UID文档异常:返回全部文档问题
Firestore查询数组不包含指定元素的错误分析与解决方案
错误原因
你使用whereField("group", notIn: [userProfile.uid])的逻辑完全错误。Firestore的notIn操作符针对数组类型字段时,判断的是整个数组是否不在指定的数组列表中,而不是数组是否不包含某个元素。
举个例子:你的查询相当于要求group数组的完整值不等于[liwIbfyZjUSVcXbhhxQUMR1fQ4p2],但你返回的文档中,group要么是["RRPtSbWZTEYKgBVQbxpCJROOcQ33"],要么是包含多个UID的数组,这些都满足“整个数组不等于单元素的UID数组”,所以所有文档都被返回了。
而arrayContains是专门判断数组是否包含指定元素的操作符,所以它能正常工作。
解决方案
Firestore目前没有提供直接的arrayDoesNotContain查询操作符,你可以通过以下两种方式实现需求:
方案1:客户端过滤
先查询集合内的所有文档(如果有其他过滤条件可以先加上),然后在客户端筛选出group数组不包含当前UID的文档:
func grabDocuments() { guard let userProfile = UserService.currentUserProfile else { return } let currentUID = userProfile.uid print(currentUID) Firestore.firestore().collection("all") .addSnapshotListener { (querySnapshot, err) in guard let snapshot = querySnapshot, err == nil else { return } // 客户端过滤:筛选group数组不包含当前UID的文档 let filteredDocs = snapshot.documents.filter { doc in let group = doc.data()["group"] as? [String] ?? [] return !group.contains(currentUID) } if !filteredDocs.isEmpty { self.dataExists() for document in filteredDocs { let group = document.data()["group"] as? [String] ?? [] print("---------------------------") print(group) print("---------------------------") } } } }
方案2:优化数据结构
如果集合文档量很大,客户端过滤效率较低,可以优化数据结构。给每个文档添加一个memberMap字段(字典类型),键为用户UID,值设为true:
// 文档示例结构 { "group": ["RRPtSbWZTEYKgBVQbxpCJROOcQ33", "liwIbfyZjUSVcXbhhxQUMR1fQ4p2"], "memberMap": { "RRPtSbWZTEYKgBVQbxpCJROOcQ33": true, "liwIbfyZjUSVcXbhhxQUMR1fQ4p2": true } }
然后使用whereField查询memberMap中不存在当前UID的文档:
func grabDocuments() { guard let userProfile = UserService.currentUserProfile else { return } let currentUID = userProfile.uid print(currentUID) Firestore.firestore().collection("all") .whereField("memberMap.\(currentUID)", isEqualTo: nil) .addSnapshotListener { (querySnapshot, err) in guard let snapshot = querySnapshot, err == nil else { return } if !snapshot.documents.isEmpty { self.dataExists() for document in snapshot.documents { let group = document.data()["group"] as? [String] ?? [] print("---------------------------") print(group) print("---------------------------") } } } }
这种方式利用了Firestore对嵌套字段的查询能力,直接在服务端完成过滤,效率更高。
内容的提问来源于stack exchange,提问作者Redstain
相关产品推荐
相关产品推荐

