如何在Firestore中查询数组长度,筛选仅含1个ID的数组对应的文档
解决方案
方案1:新增冗余统计字段(官方推荐,性能最优)
Firestore本身没有原生支持按数组长度查询的语法,官方最推荐的实现方式是新增一个和数组长度同步的数字字段:
- 你可以给thread文档新增一个
readUserIDsLength字段,每次对readUserIDs做增删改操作时,同步更新这个字段的数值为当前数组的长度 - 之后直接按这个字段筛选即可,查询性能和普通字段查询完全一致,没有额外开销
对应的查询代码修改如下:
const notification = () => { channelsRef .where('channelID', '==', item.id) .get() .then((querySnapshot) => { querySnapshot.forEach((doc) => { doc.ref .collection('thread') .where('senderID', '==', item.participants[0].id) // 直接筛选数组长度为1的文档 .where('readUserIDsLength', '==', 1) .get() .then((querySnapshot) => { console.log('size', querySnapshot.size); querySnapshot.forEach((thread) => { console.log('thread数据', thread.data()); }); }); }); }); };
方案2:利用数组下标存在性查询(无字段改动,适合小长度数组场景)
如果你的业务场景中readUserIDs数组最大长度不会超过10,也不想新增字段,可以通过判断指定下标是否存在的方式来筛选:
- 要筛选数组长度恰好为1的文档,只需要满足两个条件:下标0存在、下标1不存在
- 注意:这个方法仅适用于数组元素不会为
null的场景,同时需要提前在Firestore控制台创建对应的复合索引
对应的查询代码修改如下:
const notification = () => { channelsRef .where('channelID', '==', item.id) .get() .then((querySnapshot) => { querySnapshot.forEach((doc) => { doc.ref .collection('thread') .where('senderID', '==', item.participants[0].id) // 下标0存在说明数组长度至少为1 .where('readUserIDs.0', '!=', null) // 下标1不存在说明数组长度小于2,两个条件结合就是长度恰好为1 .where('readUserIDs.1', '==', null) .get() .then((querySnapshot) => { console.log('size', querySnapshot.size); querySnapshot.forEach((thread) => { console.log('thread数据', thread.data()); }); }); }); }); };
内容的提问来源于stack exchange,提问作者Xwingoga06
相关产品推荐
相关产品推荐

