如何在Firestore查询where子句指定docID,筛选不匹配给定ID的首个集合条目?
核心结论
你可以直接在where子句中指定questions集合的文档ID作为筛选条件,只需用Firestore内置的FieldPath.documentId()方法指代文档自身ID即可,不可直接传入自定义的docID变量。
现有代码的问题修正
你编写的查询存在两处需要调整的问题:
- 筛选文档ID的第一个参数必须是
FieldPath.documentId(),而非自定义变量 not-in操作符要求传入平铺的字符串数组,不需要额外套一层方括号,同时**not-in最多仅支持传入10个元素**,如果用户已作答题目数量超过10,该查询会直接报错。
正确示例代码(Web SDK环境)
// 先拉取当前用户的已答题目ID数组 const userDoc = await db.collection('users').doc('你的用户ID').get(); const questionsAnswered = userDoc.data().questionsAnswered || []; let unAnsweredQuestion = null; // 仅已答题目少于10时可以用not-in方案 if (questionsAnswered.length < 10) { const querySnapshot = await db.collection('questions') .where(FieldPath.documentId(), 'not-in', questionsAnswered) .limit(1) .get(); if (!querySnapshot.empty) { unAnsweredQuestion = querySnapshot.docs[0].data(); // 后续业务逻辑 } }
已答题目超过10时的替代方案
如果你的业务场景中用户已答题目可能超过10道,可以用预生成随机种子的方案绕过not-in的限制:
- 给questions集合的所有题目文档新增一个
randomSeed字段,写入题目时就生成0~1之间的随机数存入该字段 - 查询时先生成一个0~1的随机起始值,查询
randomSeed大于该值、且文档ID不在最近10道已答题目列表中的题目,取第一条返回 - 如果查询无结果,将随机起始值重置为0重新查询即可,该方案可以实现全局随机拉取未答题目,性能也符合Firestore的查询优化规则。
内容的提问来源于stack exchange,提问作者Alexander McComb
相关产品推荐
相关产品推荐

