Firestore:按文档数组中的项目查询
Posted
技术标签:
【中文标题】Firestore:按文档数组中的项目查询【英文标题】:Firestore: Query by item in array of document 【发布时间】:2018-04-01 15:10:40 【问题描述】:我有 2 个集合 "photos" 和 "users" 并且 "users" 中的每个文档都有一张或多张照片带有数组的 ID。
photos > 5528c46b > name: "Photo1"
a1e820eb > name: "Photo2"
32d410a7 > name: "Photo3"
users > acd02b1d > name: "John", photos: ["5528c46b"]
67f60ad3 > name: "Tom", photos: ["5528c46b", "32d410a7"]
7332ec75 > name: "Sara", photos: ["a1e820eb"]
9f4edcc1 > name: "Anna", photos: ["32d410a7"]
我想要拥有一个或多个特定照片 ID 的所有用户。
有没有办法做到这一点?
【问题讨论】:
【参考方案1】:请参阅Henry's answer,因为我们没有提供可用的 Array Contains 查询。
很遗憾,目前还没有,虽然它在我们的路线图上。
与此同时,您需要改用地图,其形式为:
photos:
id1: true
id2: true
现在您可以通过 photos.id1 == true
过滤找到所有 id1 的用户。
在Firebase documentation 中了解有关查询此类集合的更多信息。
【讨论】:
此路线图是否已在某处发布?只是好奇。 @DanMcGrath 此功能/路线图是否有任何更新? Firestore 不允许我在没有索引每个可能的 ID 的情况下以这种方式查询数据。有什么方法不需要索引,或者有一个动态索引? @KevinBeal 提到的最大问题是,如果您需要复合查询,您可以索引键。对于任何高级查询功能来说,这都是一个非常大的问题。 @Dan McGrath 确实如此,但仅限于一个参数。你可以做.where('photos', 'array-contains', 'id1')
,但你不能做.where('photos', 'array-contains', ['id1', 'id2'])
【参考方案2】:
这里对答案进行了一些扩展,因为有些人似乎对必须为每个键创建索引感到困惑,Firestore 已经为您的数据编制了简单查询的索引,因此您可以执行类似
的简单查询documentReference.where('param','==','value').onSnapshot(...)
但您不能进行复合查询,除非您为这些参数的数据编制索引。所以你需要索引才能做这样的事情:
documentReference.where('param','==','value').where(..otherparams...).onSnapshot(...)
所以只要你需要照片作为 id 就可以保存为
usersCollection : (a collection)
uidA: (a document)
photoField: (a field value that is a map or object)
fieldID1 : true (a property of the photoField)
fieldID2 : true (a property of the photoField)
etc ...
并且您可以简单地查询在他们的 photoField 中具有 fieldID1 的用户,而无需形成任何索引以及下面的类似查询。
firestore.doc('usersCollection/uidA').where('photoField.fieldID1','==',true).onSnapshot(...)
【讨论】:
【参考方案3】:添加了 'array-contains' 查询运算符,用于与 .where() 一起查找数组字段包含特定元素的文档。
https://firebase.google.com/support/release-notes/js5.3.0
更新:也可以在@google-cloud/firestore
:https://github.com/googleapis/nodejs-firestore/releases/tag/v0.16.0
更新 2 https://firebase.googleblog.com/2018/08/better-arrays-in-cloud-firestore.html
Update 3 现已在 Admin Node.js SDK v6.0.0 https://github.com/firebase/firebase-admin-node/releases
中提供【讨论】:
Welp 花了一段时间 :D 我正在做一个我需要这个的项目,我很高兴我落后到足以让 firebase 团队领先:p 不幸的是,没有办法用很少的“数组包含”值进行查询。 @BohdanDidukh 你试过链接他们吗? .where(..).where(...)? @Henry,是的,我试过了。 Firebase 服务器以错误响应我:FirebaseError:无效查询。查询仅支持单个数组包含过滤器。 是否可以使用对象键的值来查询对象数组,例如 arrayItems:[id:123, ...., id: 234, ...]...并做类似 .where('arrayItems', 'array-contains', 'id=123')?该语法似乎不起作用,但我仍然希望有一种方法可以做类似的事情。请指教【参考方案4】:截至 2019 年 11 月,Firestore 现在添加了一个“in”查询。 根据the announcement article:
使用 in 查询,您可以查询特定字段的多个值 (最多 10 个)在单个查询中。您可以通过传递一个包含 您要搜索的所有值,Cloud Firestore 将匹配 其字段等于这些值之一的任何文档。
【讨论】:
【参考方案5】:使用 Firebase 版本 9(2021 年 12 月更新):
您可以在 "while()" 中使用 "array-contains" 和 一个照片文档 ID 来获取 所有拥有它的用户:
import
query,
collection,
where,
getDocs
from "firebase/firestore";
// Here
const q = query(
collection(db, "users"),
where("photos", "array-contains", "5528c46b")
);
// Here
const usersDocsSnap = await getDocs(q);
usersDocsSnap .forEach((doc) =>
console.log(doc.data()); // "John's doc", "Tom's doc"
);
您还可以在 "while()" 中将 "array-contains-any" 与 一个或多个带有数组的照片文档 ID 结合使用 strong> 获取更多对应用户:
import
query,
collection,
where,
getDocs
from "firebase/firestore";
// Here
const q = query(
collection(db, "users"),
where("photos", "array-contains-any", ["5528c46b", "a1e820eb"])
);
// Here
const usersDocsSnap = await getDocs(q);
usersDocsSnap .forEach((doc) =>
console.log(doc.data()); // "John's doc", "Tom's doc", "Sara's doc"
);
【讨论】:
以上是关于Firestore:按文档数组中的项目查询的主要内容,如果未能解决你的问题,请参考以下文章