Firebase云函数查询报错:INVALID_ARGUMENT 析取数超30上限
Firebase Firestore 查询错误:Too many disjunctions after normalization
错误原因
Firestore处理多个in条件时,会将每个in数组的元素展开为逻辑或(disjunction)的组合,最终计算总组合数。你的查询中:
parent_id的in数组有5个元素text的in数组有7个元素
两者的笛卡尔积是5×7=35个组合,超过了Firestore允许的最大30个disjunctions限制,因此触发该错误。
解决方案
1. 拆分in条件为多个查询
将其中一个in数组拆分成多个小批次,分别执行查询后合并结果。比如拆分text数组为两组:
// 拆分text数组为两个批次 const textBatches = [["0","1","2","3"], ["4","5","6"]]; const finalDocs = []; for (const batch of textBatches) { const querySnapshot = await db.collection('object_relationships') .where('parent_id', 'in', ["g4gt4554y54y544y54", "jk88i7i8i87i87i87i", "vfdvfd32e3232", "bgfbfgr432r43", "bngbgfg2332rr23"]) .where('type', '==', 'worker') .where('child_id', '==', "hjew7843yu3r783y3r783r") .where('text', 'in', batch) .get(); querySnapshot.forEach(doc => finalDocs.push(doc)); } // 可选:如果存在重复文档(理论上不会,除非条件重复),执行去重 const uniqueDocs = [...new Map(finalDocs.map(doc => [doc.id, doc])).values()];
2. 调整数据结构
如果这类查询频繁,可以新增一个复合字段(比如parent_text),将parent_id和text的组合预存在该字段中,然后用单个in条件包含所有需要的组合(注意组合总数不能超过30):
比如存储文档时新增字段:
// 写入文档时添加复合字段 await db.collection('object_relationships').add({ parent_id: "g4gt4554y54y544y54", text: "0", parent_text: "g4gt4554y54y544y54_0", // 其他字段... });
查询时使用单个in:
const targetCombinations = [ "g4gt4554y54y544y54_0", "g4gt4554y54y544y54_1", // 所有需要的parent_id+text组合,总数不超30 ]; const output = await db.collection('object_relationships') .where('parent_text', 'in', targetCombinations) .where('type', '==', 'worker') .where('child_id', '==', "hjew7843yu3r783y3r783r") .get();
3. 客户端过滤
如果parent_id的查询结果集不大,可以先执行parent_id+其他==条件的查询,再在客户端过滤text字段:
const snapshot = await db.collection('object_relationships') .where('parent_id', 'in', ["g4gt4554y54y544y54", "jk88i7i8i87i87i87i", "vfdvfd32e3232", "bgfbfgr432r43", "bngbgfg2332rr23"]) .where('type', '==', 'worker') .where('child_id', '==', "hjew7843yu3r783y3r783r") .get(); const targetTexts = new Set(["0","1","2","3","4","5","6"]); const filteredDocs = []; snapshot.forEach(doc => { if (targetTexts.has(doc.data().text)) { filteredDocs.push(doc); } });
这个方法要注意:如果parent_id的查询结果很大,会消耗较多读取量,且客户端过滤性能会下降,仅适合小数据集场景。
内容的提问来源于stack exchange,提问作者Matt Booth
相关产品推荐
相关产品推荐

