如何查询Firestore中排除用户文档黑名单数组内的所有用户?
当前你用数组存储拉黑用户ID的方式,确实没法直接用Firestore的查询操作符实现"排除拉黑用户"的需求,下面是几种可行的数据库结构调整方案:
方案一:将拉黑列表改为键值对映射
把原来的blockedUsersId数组换成对象结构,用被拉黑用户的ID作为键,值设为true(或时间戳)。这样就能通过Firestore的!=或not-exists操作符来过滤被拉黑的用户。
示例结构:
users: { user1:{ name: "Lorem Ipsum", blockedUsers: { "user2": true, "user3": true } } }
查询逻辑:当你要查询某个用户(比如targetUser)是否未被当前用户拉黑时,可以用where("blockedUsers." + targetUser.id, "!=", true),或者直接检查该键是否不存在:where("blockedUsers." + targetUser.id, "not-exists")。
这个方案的优点是查询直接,无需额外集合;需要注意的是单文档大小限制(Firestore单文档最大1MB),如果用户拉黑上千人可能会触及上限,一般场景下足够用。
方案二:新建独立的拉黑关系集合
单独创建一个blockedRelations集合,每个文档存储一条拉黑记录,包含拉黑者ID和被拉黑者ID。
示例结构:
blockedRelations: { doc_abc123: { blockerId: "user1", blockedId: "user2" }, doc_def456: { blockerId: "user1", blockedId: "user3" } }
查询逻辑:
- 先从
blockedRelations中查询当前用户(比如user1)所有拉黑的用户ID,得到一个列表blockedIds; - 再查询用户集合时,用
where("userId", "not-in", blockedIds)排除拉黑用户。
注意:Firestore的not-in操作符最多支持10个元素,如果拉黑人数超过10,需要分批查询后在客户端合并结果,或者结合分页逻辑处理。这个方案适合拉黑量很大的场景,不会出现单文档过大的问题。
方案三:客户端过滤(仅适合小用户量场景)
如果你的应用用户基数很小,可以先查询全部用户列表,然后在客户端代码中过滤掉当前用户拉黑列表里的ID。这种方式开发最快,但用户量增大后会导致查询数据量过大,性能和流量消耗都会上升,仅适合初期小范围测试或小众应用。
内容的提问来源于stack exchange,提问作者Fortray

