在Firestore中能否用OR逻辑查询两个字段中的用户ID?
Firestore是否支持OR逻辑查询及实现方案
首先明确:Firestore不支持你代码里写的那种直接在单个whereField中添加OR条件的语法,但有两种可靠方式实现你要的「当前用户是邀请发送者或接收者」的查询逻辑:
方法一:使用whereFilter构建复合OR查询
从Firebase SDK 9.0+(Swift对应FirebaseFirestore 9.0+)开始,官方支持用Filter.or组合多个条件实现OR查询,示例代码如下:
guard let currentUserId = Auth.auth().currentUser?.uid else { // 处理用户未登录的异常情况 return } // 构建两个单条件过滤器 let senderFilter = Filter.whereField("idenvoyeur", isEqualTo: currentUserId) let receiverFilter = Filter.whereField("idreceveur", isEqualTo: currentUserId) // 组合OR条件发起查询 db.collection("Invitations") .whereFilter(Filter.or([senderFilter, receiverFilter])) .getDocuments { snapshot, error in if let error = error { print("查询失败:\(error.localizedDescription)") return } guard let documents = snapshot?.documents else { print("未找到相关邀请记录") return } // 将文档解析为自定义结构体 let invitations = documents.compactMap { doc -> Invitations? in try? doc.data(as: Invitations.self) } // 处理查询到的邀请数据 }
方法二:发起两个独立查询后合并结果
如果你的SDK版本较低,不支持Filter.or,可以分别查询「当前用户是发送者」和「当前用户是接收者」的文档,再在客户端合并并去重结果:
guard let currentUserId = Auth.auth().currentUser?.uid else { return } // 定义两个独立查询 let senderQuery = db.collection("Invitations") .whereField("idenvoyeur", isEqualTo: currentUserId) let receiverQuery = db.collection("Invitations") .whereField("idreceveur", isEqualTo: currentUserId) // 用调度组并行执行查询 let dispatchGroup = DispatchGroup() var senderInvitations: [Invitations] = [] var receiverInvitations: [Invitations] = [] dispatchGroup.enter() senderQuery.getDocuments { snapshot, error in defer { dispatchGroup.leave() } if let error = error { print("发送者查询失败:\(error.localizedDescription)") return } senderInvitations = snapshot?.documents.compactMap { try? $0.data(as: Invitations.self) } ?? [] } dispatchGroup.enter() receiverQuery.getDocuments { snapshot, error in defer { dispatchGroup.leave() } if let error = error { print("接收者查询失败:\(error.localizedDescription)") return } receiverInvitations = snapshot?.documents.compactMap { try? $0.data(as: Invitations.self) } ?? [] } // 等待所有查询完成后合并去重 dispatchGroup.notify(queue: .main) { let allInvitations = senderInvitations + receiverInvitations // 用文档ID作为唯一标识去重(如果你的结构体没有存储文档ID,可临时修改结构体添加) let uniqueInvitations = Dictionary(uniqueKeysWithValues: allInvitations.map { ($0.idenvoyeur + $0.idreceveur + $0.datedelenvoi.timeIntervalSince1970.description, $0) }).values // 处理去重后的邀请数据 }
额外优化方案:调整数据结构(可选)
如果这类OR查询是高频操作,建议优化Firestore的数据结构:给每个邀请文档添加participants数组字段,包含发送者和接收者的ID,然后用arrayContains做单条件查询,效率更高。
修改后的结构体:
struct Invitations: Codable { enum EtatDeValidationDeLInvitation: String, Codable { case encours case accepter } var idenvoyeur = "" var idreceveur = "" var participants: [String] { [idenvoyeur, idreceveur] } var datedelenvoi: Date = Date() var statutdelinvitation: EtatDeValidationDeLInvitation = .encours }
查询代码:
guard let currentUserId = Auth.auth().currentUser?.uid else { return } db.collection("Invitations") .whereField("participants", arrayContains: currentUserId) .getDocuments { snapshot, error in // 结果处理逻辑和方法一一致 }
内容的提问来源于stack exchange,提问作者Christine
相关产品推荐
相关产品推荐

