繁体   English   中英

对 documentId 的 Firestore 集合组查询

[英]Firestore collection group query on documentId

在我的场景中,用户可以“喜欢”另一个用户的个人资料。 结果,我为每个用户创建了一个名为“likedBy”的子集合,我在其中为特定用户创建了一个文档,例如:

users(col) -> User A(doc) -> likeBy(col) -> User B (doc), User C (doc)

因此,在用户被删除的罕见情况下,我想删除该用户的所有喜欢问题。

我只是不确定这是否可能(一种解决方法可能是在所述文档中再次保存 userId 并查询)。

我基本上正在寻找的是这样的:

db.collectionGroup('likedBy').where(firebase.firestore.FieldPath.documentId(), '==', "User A").get();

问题是,我无法在 Firestore 控制台中为 documentId 创建索引。

更新 2020-01-23:

有关这方面的更新,请参阅群组板上与 Sam Stern 的对话: https : //groups.google.com/d/msgid/google-cloud-firestore-discuss/e1b47358-b106-43a0-91fb-83c97d6244de%40googlegroups。电脑

大部分讨论来自一个明显的事实,即基于文档的完全限定路径(因此只需要在“集合中”是唯一的),数据库中的所有记录都有一个“主索引”。

为了“加速”文档引用,JS SDK 实际上将集合路径“前置”到 .doc 中传递的任何信息上,以“方便地”使用该主索引

即所有这些都是完全等效的

db.doc('collection/docId/collection/docId/collection/docId")
db.collection('collection").doc("docId/collection/docId/collection/docId")
db.collection('collection").doc("docId").collection("collection").doc("docId/collection/docId")
db.collection('collection").doc("docId").collection("collection").doc("docId").collection("collection").doc("docId")
db.doc("collection/docId").collection("collection").doc("docId").collection("collection").doc("docId")
db.collection("collection/docId/collection").doc("docId").collection("collection").doc("docId")
db.doc("collection/docId/collection/docId").collection("collection").doc("docId")
db.collection("collection/docId/collection/docId/collection").doc("docId")

--- 他们都创建了相同的索引引用“collection/docId/collection/docId/collection/docId”以在“主索引”中查找文档。

(在我一点也不谦虚的意见中) FieldPath.documentId() 被实现(错误地)以“方便地”匹配此行为,因此需要完全限定的路径,而不是 docId,当它应该像任何一样实现时其他查询,并且需要创建和维护一个 NEW INDEX 来容纳该查询。

此行为的代码是在实现 collectionGroups 之前编写的 - 并且从未记录过使用的 hack 与使用的 METHOD NAME 不匹配。

解决方法是要求编码器将 docId 作为字段复制到每个文档中,并在其上编写您的查询。 我已经在 Firestore.js 和我的应用程序之间编写了自己的层来抽象行为,并且可能只是将其实现为库的基本功能。

但这显然是一个错误,到目前为止,每个人都一直试图告诉我这是有道理的,并且他们将更改文档以匹配现有行为(但不是方法名称)。

正如我之前写的那样,我不断收到一堆破烂的雏菊,并被告知“看到了吗?这些是玫瑰!文件称它们为玫瑰!任何其他名字的玫瑰闻起来都很甜,等等!!”

除非他们感到尴尬,否则不会更新

2020 年 1 月 10 日更新:我构建了一个演示应用程序,显示了确切的错误,并已根据要求将其发送给 Firebase 支持。 出于某种原因,支持小动物将其视为“功能请求”,尽管它显然是一个错误。 当以“/ShowInfo/showID”形式调用 URL 时,应用会匿名登录 Firebase Auth; 然后使用 FieldPath.documentId() "==" showID 在 collectionGroup(3 层深)上调用查询

它使查询 3 种方式:

1) 仅使用 showID- 时会因熟悉的“无效查询”而失败。当通过 FieldPath.documentId() 查询集合组时,提供的值必须产生有效的文档路径,但 'pqIPV5I7UWne9QjQMm72'(实际的 showID)是不是因为它有奇数个段 (1)。”

2) 使用“相对路径”(/Shows/showID) 一次,它没有错误,但不返回任何文档。

3) 最后使用“完整路径”(/Artists/ArtistID/Tour/tourID/Shows/showID)。 这没有错误,并且确实返回了一个文档 - 但是如果我有完整路径,为什么我需要在 collectionGroup 上进行查询? 而且我没有完整路径 - showID(上面)作为 URL 的一部分(显然是节目数据的链接) - 我手工伪造了它以进行测试。

等待回应。

2019 年 12 月 2 日更新:Firebase 支持人员联系询问我是否仍希望解决此问题。 呃。

更新 2019-09-27:Firebase 支持人员承认这是一个错误。 什么时候修好还没有说。 实际上,documentId()应该能够直接用于文档 ID。

documentID可以用作查询的一部分,但正如上面@greg-ennis 所指出的,它需要偶数个段。 事实证明,如果您确实需要一个 collectionGroup(我确实需要),那么要比较的“Id”需要将 collectionGroup ID/name冗余添加为一个段:

db.collectionGroup('likedBy')
.where(firebase.firestore.FieldPath.documentId(), '==', "likedBy" + "/" + "User A")
.get();

我用过它并且它(*sorta)有效。 (诚​​然,我花了 2 个小时才弄明白,上面的问题有助于集中搜索)

另一方面,这种特定情况不是您想要使用 collectionGroup 的地方。 记住采集组-指AA组单独收集,好像他们是一个办法。 在这种情况下,保存“用户 A”喜欢的“集合”作为“用户 A”文档下的集合存在。 在删除“用户 A”的文档之前只需删除单个集合。 没必要把其他人的喜好都带进来。

Sorta:显然比较的字段路径必须是文档的完整路径。 如果您知道 documentId,但由于“原因”,您不知道完整路径包括子集合所属的文档(这就是为什么您首先使用 collectionGroup 方法的原因),现在这似乎有点死路。 继续努力。

验证和错误报告提交:FieldPath.documentID()反对documentId比较; 它与完全分段的文档路径进行比较,正如您必须提供给 .doc(path) 一样:

即:在“TopCollection/document_this/NextCollection/document_that/Travesty/document_Id_I_want”中找到一个文档

使用集合组“Travesty”

db.collectionGroup("Travesty")
.where(firebase.firestore.FieldPath.documentId(), '==', "document_id_I_want")

……失败,但是……

db.collectionGroup("Travesty")
.where(firebase.firestore.FieldPath.documentId(), '==', "TopCollection/document_this/NextCollection/document_that/Travesty/document_Id_I_want")
.get()

……成功。 这使得这毫无用处,因为如果我们拥有所有这些信息,我们将只使用:

db.doc("TopCollection/document_this/NextCollection/document_that/Travesty/document_Id_I_want")
.get()

您无法使用以下查询:

db.collectionGroup('likedBy').where(firebase.firestore.FieldPath.documentId(), '==', "User A").get();

这是因为集合组查询仅适用于文档属性而不适用于文档 ID。 根据有关集合组查询的官方文档:

db.collectionGroup('landmarks').where('type', '==', 'museum');

您查询了landmarks子集合,其中type属性保存了museum的值。

解决方法可能是将用户的 id 存储在数组中并使用array-contains但请记住,对于您使用的每个集合组查询,您都需要一个索引,但不幸的是,您无法以编程方式创建这样的索引。 即使您可以在 Firebase 控制台中创建索引,它也无济于事,因为您是动态获取这些 id 的。 所以不是为每个用户单独创建索引的选项,因为您将很快达到最大数量的索引

数据库的最大复合索引数:200

要解决此类问题,您应该考虑在每个用户对象下添加一个数组并使用如下查询:

usersRef.where("usersWhoLikedMe", "array-contains", "someUserId")

其中usersWhoLikedMe是数组类型的属性。

如果您将用户 A 和 B id 添加到文档本身:

users(col) -> User A(doc) -> likedBy(col) -> User B ({user_id: B, profile_liked_id: A})

然后您可以使用以下方法进行查询:

db.collectionGroup('likedBy').where('user_id', '==', 'B');

如果引用是一个集合,则您比较的值需要是文档 ID(完整路径的最后一段)

如果引用是一个collectonGroup,你比较的值需要是一个完整的文档路径<--在我看来这是非常多余的

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM