如何在Kotlin中为Firestore实现多WhereNotIn查询?
解决Firestore多条件WhereNotIn查询的限制问题
Firestore确实只允许单个whereNotIn查询,无法直接链式调用多个。针对你需要同时排除被屏蔽用户和日记的场景,可通过以下方式实现需求:
方案一:客户端二次过滤(最直接)
先通过单个whereNotIn过滤掉其中一类数据,再在客户端对结果进行二次过滤,排除另一类不符合条件的文档。建议优先过滤数据量更大的集合,减少客户端需要处理的数据量。
修改你的代码如下:
var storeBuilder: Query? userDB.document("$userId") .get() .addOnSuccessListener { document -> val blockedUser = document.data?.getValue("blockedUser") as? ArrayList<String> ?: arrayListOf() val blockedDiary = document.data?.getValue("blockedDiary") as? ArrayList<String> ?: arrayListOf() when { blockedUser.isNotEmpty() && blockedDiary.isNotEmpty() -> { // 先通过whereNotIn过滤被屏蔽的日记 diaryDB.whereNotIn("diaryId", blockedDiary) .get() .addOnSuccessListener { querySnapshot -> // 客户端过滤掉被屏蔽用户的日记 val filteredDiaries = querySnapshot.documents.filter { doc -> !blockedUser.contains(doc.getString("userId")) } // 处理filteredDiaries数据 } } blockedUser.isNotEmpty() -> { storeBuilder = diaryDB.whereNotIn("userId", blockedUser) // 执行查询并处理结果 } blockedDiary.isNotEmpty() -> { storeBuilder = diaryDB.whereNotIn("diaryId", blockedDiary) // 执行查询并处理结果 } else -> { storeBuilder = diaryDB // 执行查询并处理结果 } } }
方案二:拆分查询合并结果(适用于列表元素过多的情况)
如果blockedUser或blockedDiary的元素数量超过50(FirestorewhereNotIn的上限),需要将列表拆分为多个子列表,分别执行查询后合并结果,再进行客户端过滤。
示例(以拆分blockedDiary为例):
fun splitList(list: List<String>, chunkSize: Int = 50): List<List<String>> { return list.chunked(chunkSize) } // 在需要处理的地方: val splitBlockedDiaries = splitList(blockedDiary) val tasks = mutableListOf<Task<QuerySnapshot>>() splitBlockedDiaries.forEach { chunk -> tasks.add(diaryDB.whereNotIn("diaryId", chunk).get()) } Tasks.whenAllSuccess<QuerySnapshot>(tasks) .addOnSuccessListener { results -> val allDocuments = results.flatMap { it.documents } // 再过滤blockedUser val filteredDiaries = allDocuments.filter { doc -> !blockedUser.contains(doc.getString("userId")) } // 处理最终数据 }
注意事项
- 客户端过滤会增加本地数据处理的开销,若数据集过大,建议结合分页查询减少单次加载的数据量。
- 如果对数据实时性要求高,可以考虑使用Cloud Functions在后端完成过滤逻辑,客户端直接获取处理后的结果。
内容的提问来源于stack exchange,提问作者Hyejung
相关产品推荐
相关产品推荐

