javascript 对documentId的Firestore集合组查询

oxiaedzo  于 2023-05-27  发布在  Java
关注(0)|答案(5)|浏览(93)

在我的场景中,用户可以“喜欢”另一个用户的配置文件。因此,我为每个用户创建了一个名为“likedBy”的子集合,在这里我为特定用户创建了一个文档,例如:
users(col)-> User A(doc)-> likedBy(col)-> User B(doc),User C(doc)
因此,在用户被删除的罕见情况下,我想删除该用户的所有喜欢问题。
我只是不确定这是否可能(一个解决方案可能是在所述文档中再次保存userId并查询)。
我基本上在寻找的是这样的东西:

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

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

rm5edbpk

rm5edbpk1#

更新2020-01-23:
有关这方面的更新,请参阅小组董事会上与Sam Stern的对话:https://groups.google.com/d/msgid/google-cloud-firestore-discuss/e1b47358-b106-43a0-91fb-83c97d6244de%40googlegroups.com
大部分讨论都来自一个明显的事实,即数据库中的所有记录都有一个基于文档的完全限定路径的“主索引”(因此只需要在“集合”中是唯一的)。
为了“加速”文档引用,JSSDK实际上将集合路径“预先挂起”到.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'来在“主索引”中查找文档。
(in我一点也不谦虚)FieldPath.documentId()被实现(不正确地)以“方便地”匹配这种行为,因此需要完全限定的路径,而不是docId,当它 * 应该 * 像任何其他查询一样被实现时,并且需要创建和维护一个新的索引来适应查询。
这种行为的代码是在实现collectionGroups之前编写的-并且从未记录过所使用的hack与所使用的METHOD NAME不匹配。
解决方法是要求编码器将docId复制为每个文档中的字段,并在其上编写查询。我已经在Firestore.js和我的应用程序之间编写了自己的层来抽象行为,并且可能会简单地将其实现为库的基本功能。
但这显然是一个错误,到目前为止,每个人都试图告诉我这是有意义的,他们将更改文档以匹配现有的行为(但不是方法名称)。
正如我之前所写的,我不断地得到一束破烂的雏菊,并被告知“看到了吗?这些是玫瑰!文件上说是玫瑰!玫瑰不管叫什么名字,闻起来都一样香!!”

不丢人就不更新

更新2020-01-10:我已经建立了一个演示应用程序显示确切的错误,并已将其发送到Firebase支持的要求。由于一些该死的原因,支持者认为这是一个“功能请求”,尽管它显然是一个错误。以“/ShowInfo/showID”形式调用URL时,App匿名登录Firebase Auth;然后使用FieldPath.documentId()“==”showID调用collectionGroup(3层)上的查询
它使查询有3种方式:
1)有一次只使用showID-这会因为熟悉的“Invalid query”而失败。当通过FieldPath.documentId()查询集合组时,提供的值必须导致有效的文档路径,但'pqIPV 5I 7 UWne 9 QjQMm 72'(实际的showID)不是,因为它具有奇数个段(1)。”
2)一次使用“Relative Path”(/Shows/showID),它没有错误,但不返回文档。
3)最后使用“完整路径”(/Artists/ArtistID/Tour/tourID/Shows/showID)。这没有错误,并且 does 返回一个文档-但是如果我有完整的路径,为什么我需要在collectionGroup上查询?我没有完整的路径--showID(上面)是作为URL的一部分(很明显,是指向show数据的链接)--我在测试中伪造了它。

等待响应。

更新2019-12-02:Firebase支持部门伸出手来问我是否还想解决这个问题。废话
更新2019-09-27:Firebase支持已经承认这是一个错误。没有人说什么时候会被修复。documentId()* 应该 ,实际上,能够直接用于 * 仅 * 文档ID。
documentID * 可以 * 用作查询的一部分,但是,正如@greg-ennis上面提到的,它需要偶数个段。事实证明,
如果 * 你真的需要一个collectionGroup(我确实需要),那么要比较的“Id”需要 * 冗余地 * 添加collectionGroup ID/名称作为一个段:

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

我用过它,它(*sorta)工作。(诚然,我花了2个小时才弄明白,上面的问题帮助集中了搜索的重点)
另一方面,this 特定情况 * 不是 * 您想要使用collectionGroup的地方。记住什么是集合组 * -一种引用一组 * 独立集合 * 的方法,就好像它们是一个集合一样。在这种情况下,保存“用户A”喜欢的“集合”作为“用户A”的文档下的集合存在。在删除“用户A”的文档之前,只需删除 * 该 * 单个集合。没必要把其他人的喜好也扯进来。
Sorta:比较的字段路径显然必须是文档的完整路径。如果你知道documentId,但由于“原因”你不知道 * 完整路径 包括 * 子集合是哪个文档的一部分(有点为什么你首先使用collectionGroup方法),现在这似乎是一个致命的死胡同。继续努力。
验证并提交缺陷报告:documentID()不与documentId进行比较;它与完全分段的文档路径进行比较,就像您必须提供给.doc(path)一样:
也就是说:在“TopCollection/document_this/NextCollection/document_that/Travesty/document_Id_I_want”中查找文档
使用collectionGroup“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()
kgsdhlau

kgsdhlau2#

无法使用以下查询:

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是数组类型的属性。

lo8azlld

lo8azlld3#

如果将用户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');
vmpqdwk3

vmpqdwk34#

如果引用是一个集合,则比较的值必须是文档ID(完整路径的最后一段)
这是一个错误消息,如果你违反了规则
无效查询。通过documentId()查询集合时,必须提供纯文档ID,但“a/b/c”包含“/”字符
如果引用是一个collectonGroup,则与之比较的值需要是一个完整的文档路径<--在我看来这是非常多余的
无效查询。当通过documentId()查询集合组时,提供的值必须导致有效的文档路径,但'a/b/c'不是,因为它具有奇数个段(3)
最近测试

nwlqm0z1

nwlqm0z15#

老问题了,但是你不能通过将likedById添加到文档本身来绕过这一切吗?

/users/userA/likedBy/userB = {
  likedById: 'userB',
  otherData: 'whatever',
}

然后,您可以像这样查询,而不是在documentId()上查询,这是有争议的

collectionGroup('likedBy').where('likedById', '==', 'userA')

当然,它需要将基本上是文档ID的内容反规范化到文档数据中,但是如果您没有宝贵的文档ID,firestore确实是最好的。如果你的数据模型可以在每个documentid都是一个随机的uuid(或其他什么)的情况下工作,那么你比拥有一些特殊文档的子树要好得多。

相关问题