如何查询Firestore文档内的对象数组 筛选含指定ID的对象
问题解答
你当前的写法不正确,无法返回预期的查询结果。
错误原因
Firestore的array-contains操作符对数组内的对象做匹配时,属于完整精确匹配:要求传入的查询值和数组中存储的对象所有属性、属性值、属性顺序完全一致,不支持仅传入对象的单个属性做部分匹配。
除此之外你的代码还有两处细节问题:
- 你传入的匹配值只有
id属性,和数组内存储的带name/age/id三个属性的完整员工对象不匹配 - 你示例里存储的员工
id是数字类型,查询时传入的是字符串'887878',类型不匹配也会导致查询失效 - 代码中集合名写的是
user,和你描述的集合名users不一致,也会导致查询指向错误的集合
可行实现方案
方案1:不改动现有结构,传入完整对象匹配
如果不想调整现有数据结构,使用array-contains时必须传入和数组内存储完全一致的完整对象:
const citiesRef = collection(db, 'users'); // 注意属性、值、类型都要和存储的对象完全一致 const q = query(citiesRef, where('employee', 'array-contains', {name: 'peter', age: 30, id: 887878})); const querySnapshot = await getDocs(q); querySnapshot.forEach((doc) => { console.log(doc.id, ' => ', doc.data()); });
这个方案缺点很明显:你需要提前知道员工对象的所有属性值才能查询,无法仅靠id完成筛选,实用性很低。
方案2:新增映射字段(推荐)
在用户文档中新增一个专门用于查询的数组字段,仅存储所有员工的id,比如新增employeeIds字段,存储格式为[237878, 887878]。
写入/更新员工数据时,同步维护这个字段和employee数组的id值一致即可,查询时直接对这个字段做匹配:
const q = query(citiesRef, where('employeeIds', 'array-contains', 887878));
这种写法不需要传入完整对象,仅靠id就能完成筛选,性能和实用性都更好。
方案3:改用子集合存储
如果后续需要对员工做更多维度的筛选(比如按年龄、按姓名组合查询),可以把employee从数组字段改成users集合下的子集合,每个员工作为子集合内的独立文档存储,此时就可以使用普通的文档查询逻辑,支持任意字段的筛选,灵活度最高。
内容的提问来源于stack exchange,提问作者Mahad Ahmad
相关产品推荐
相关产品推荐

