You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 20:20:16