Firestore指定ID文档查询问题:突破10个ID限制求方案
问题分析与解决方案
首先,你当前代码的问题在于Firestore的Query对象是不可变的——每次调用whereEqualTo()、whereIn()这类方法时,都会返回一个全新的Query实例,而不会修改原来的CollectionReference对象。你在循环里调用collectionReference.whereEqualTo("id", id),但根本没有把返回的新Query保存下来,最后执行get()的还是最初的collectionReference(也就是整个public_messages集合的查询),所以自然返回了所有文档。
接下来分两种场景给你解决方法,同时处理id数量超过10个的限制:
场景1:id列表长度 ≤ 10
这时候可以直接用whereIn()查询,这是Firestore官方支持的批量匹配方式:
ArrayList<String> keys = ...; // 你的id列表 CollectionReference collectionRef = firebaseFirestore.collection("public_messages"); // 使用whereIn过滤匹配id列表的文档(最多支持10个元素) Query query = collectionRef.whereIn("id", keys); query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() { @Override public void onComplete(@NonNull Task<QuerySnapshot> task) { if (task.isSuccessful()) { int count = task.getResult().size(); Log.d("TAG", "total messages = " + count); // 遍历匹配到的文档 for (QueryDocumentSnapshot doc : task.getResult()) { // 这里写你的文档处理逻辑 } } else { Log.d("TAG", "Error getting documents: ", task.getException()); } } });
另外,你提到每个文档的generatedId和id字段值相同,其实可以直接通过文档ID查询(比查字段更高效),用getAll()方法:
ArrayList<String> keys = ...; List<DocumentReference> docRefs = new ArrayList<>(); for (String id : keys) { docRefs.add(firebaseFirestore.collection("public_messages").document(id)); } firebaseFirestore.getAll(docRefs).addOnCompleteListener(new OnCompleteListener<List<DocumentSnapshot>>() { @Override public void onComplete(@NonNull Task<List<DocumentSnapshot>> task) { if (task.isSuccessful()) { int count = 0; for (DocumentSnapshot doc : task.getResult()) { if (doc.exists()) { // 确保文档确实存在 count++; // 处理文档 } } Log.d("TAG", "total messages = " + count); } else { Log.d("TAG", "Error getting documents: ", task.getException()); } } });
场景2:id列表长度 > 10
由于Firestore的whereIn和getAll都最多支持10个元素,这时候需要把id列表拆分成多个最多10个元素的子列表,并行发起查询后合并结果。
用Tasks.whenAll()来等待所有查询完成,然后合并结果:
ArrayList<String> keys = ...; // 长度超过10的id列表 CollectionReference collectionRef = firebaseFirestore.collection("public_messages"); // 拆分id列表为多个子列表,每个最多10个元素 List<List<String>> idChunks = new ArrayList<>(); for (int i = 0; i < keys.size(); i += 10) { int endIndex = Math.min(i + 10, keys.size()); idChunks.add(keys.subList(i, endIndex)); } // 为每个子列表创建查询任务 List<Task<QuerySnapshot>> queryTasks = new ArrayList<>(); for (List<String> chunk : idChunks) { Query query = collectionRef.whereIn("id", chunk); queryTasks.add(query.get()); } // 并行执行所有任务,等待全部完成后合并结果 Tasks.whenAll(queryTasks).addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if (task.isSuccessful()) { List<QueryDocumentSnapshot> allMatchedDocs = new ArrayList<>(); // 遍历每个查询的结果,合并有效文档 for (Task<QuerySnapshot> singleTask : queryTasks) { if (singleTask.isSuccessful()) { allMatchedDocs.addAll(singleTask.getResult()); } else { // 处理单个子查询的错误 Log.d("TAG", "Error in chunk query: ", singleTask.getException()); } } Log.d("TAG", "total messages = " + allMatchedDocs.size()); // 处理合并后的文档列表 } else { Log.d("TAG", "Error waiting for all queries: ", task.getException()); } } });
如果是用文档ID查询的方式,逻辑类似:拆分文档引用列表为10个一组,用getAll()批量查询,再合并结果即可。
内容的提问来源于stack exchange,提问作者Usman
相关产品推荐
相关产品推荐

