该文档不存在,也不会出现在查询或快照中,但结构相同的文档有效

Posted

技术标签:

【中文标题】该文档不存在,也不会出现在查询或快照中,但结构相同的文档有效【英文标题】:This document does not exist and will not appear in queries or snapshots, but identically structured document works 【发布时间】:2018-04-13 02:37:08 【问题描述】:

前言:这个问题已经被问到here 但用户放弃并给出了第一个答案的解决方案。这个问题的不同之处还在于我有两个相似的集合结构,但错误只发生在其中一个上。

我正在使用 Google 的新 Firestore 数据库,并创建了以下结构:区域/区域列表/调度/调度列表/调度信息

我们使用 this method 在后端使用 Firebase Admin SDK 创建自定义令牌。当用户登录我们的后端时,我们生成令牌并将他们有权访问的区域添加为附加声明,我们打算从安全规则中的 auth / request.auth 对象访问这些声明,以限制他们对调度文档的访问因此。我会提到这一点,以防我们对结构的处理不正确,在这种情况下,请纠正我,因为我们是 Firestore 的新手。

我们遇到的问题是其中一个文档给出了警告:“此文档不存在,不会出现在查询或快照中”(见下图)。但是,我们有一个相同的文档结构(图像中的文档 7),它没有发出此警告,并且确实出现在查询和快照中。

【问题讨论】:

【参考方案1】:

这告诉您territories/6 不作为实际文档存在,而territories/7 存在。

在 Cloud Firestore 中,可能有“虚拟”文档拥有的子集合 - 也就是说,更高级别的文档不存在,但它有子集合。

这些虚拟文档可以很容易地组织信息,而无需创建重复的虚拟文档。

在这种情况下,您可以:

    之前在territories/6下创建了一堆dispatch文件 您创建了 territories 文档,或者 您随后删除了territories/6,但没有删除子集合文档。

【讨论】:

那有没有办法在创建子集合时动态创建文档呢?也就是说,如果 OP 想要添加 territories/10/dispatches/...,他是否需要先添加 10,然后再添加 dispatches?可以推断:db.collections("territories").document("10").collection("dispatches").add("...") 会为他做这件事,但我认为情况并非如此。 你能回答@Jaywaa 的问题吗?有没有办法在创建长链集合和文档的同时创建非虚拟文档?请告诉我们! 单独的问题应该作为新的 Stack Overflow 问题提出,而不是在 cmets 部分提出。这使得回答更容易,确保问题/答案停留在一个主题上,也意味着更多的人可能会看到它并回答:)【参考方案2】:

不确定这是否能解决您的问题,但是否解决了我的问题...如果文档只有子集合但没有字段(我猜这被称为“虚拟”文档),控制台中的消息:"This document does not exist, it will not appear in queries or snapshots" 似乎会出现。

我使用set 方法在已经存在的“虚拟”文档上添加虚拟字段(json 对象),使它们可以通过快照或查询发现。它没有覆盖/删除这些文档的任何子集合。无法通过控制台添加字段。

我的代码:

var docRef = this.fsdb.collection('sessions')
//do for all "virtual" docs in collection
docRef.doc('mySession1').set(dummy: 'dummy')

docRef.onSnapshot(val => 
   var mySessionsArray: any [] = []
   val.forEach(myDoc => 
    mySessionsArray.push(myDoc.id)
  )
  console.log(mySessionsArray)
)

控制台:["mySession1", "mySession2", "mySession3"]

免责声明,不是专业的程序员 :-)

【讨论】:

【参考方案3】:

我能够修复这个错误,目前接受的答案只解释了原因并且没有提供修复。当我尝试在我的 Firestore 根目录中没有“用户”集合的情况下运行它时,这是导致错误的代码(对我而言):

db.collection("users").document(currentUserUID).collection("groups").addDocument(data: [
        "groupID": newGroup.documentID,
        "userAddDate": NSDate()
    ])

创建的 currentUserUID 文档引发了“文档不存在”虚拟错误。我复制了 currentUserUID 并删除了 users 集合和虚拟 UserUID 文档。

然后,我在根节点创建了一个新的“用户”集合,并粘贴了我为 userUID 复制的带有虚假字段的值。

然后当我重新运行上面的sn-p代码时,重新添加“组”集合和文档没有问题:)

【讨论】:

【参考方案4】:

一个简单的修复

一个文档需要至少有一个字段才能存在。如果一个文档只包含子集合,那么它就是一个虚拟/不存在的文档,因此它不可能出现在查询或数据快照中。

考虑添加这样的字段

  // initialize firestoreDatabase

    val firestoreDatabase : FirebaseFirestore? by lazy  FirebaseFirestore.getInstance() 

    // set at least one field
    
    firestoreDatabase.collection("territories").
                                  document("6").
                                  set(hashMapOf(
                              "key" to "value"))

对数据库中的任何其他文档执行类似的操作。

【讨论】:

【参考方案5】:

这是我的理解。在 Firebase Cloud Firestore 中,您可以创建文档而不创建其父文档。换句话说,添加“mysubdoc”而不事先创建“mydoc”是完全可以的。

[Kotlin]
FirebaseFirestore.getInstance()
    .document("/mycoll/mydoc/mysubcoll/mysubdoc").set(hashMapOf("key", "value"))

如果这样做,没有任何危害,除了您收到“此文档不存在,它不会出现在查询或快照中”警告,并且可能某些查询可能无法按预期工作。

相反,删除文档不会删除其子集合。更多信息请参考https://firebase.google.com/docs/firestore/manage-data/delete-data。

如果您确实想创建父文档,您可以执行类似以下的操作;创建一个空值的文档。

FirebaseFirestore.getInstance()
    .document("/mycoll/mydoc").set(hashMapOf<String, String>())

确保正确设置了读/写规则,尤其是当您使用用户 ID 作为文档路径的一部分以防止未经授权的用户窥探时。

如果只是一次性交易,您也可以从 Firebase 控制台创建“mydoc”。

【讨论】:

【参考方案6】:

这通常发生在集合中有空字段时,可以通过在字段中添加一个虚拟值来解决,最好是当前时间戳就足够了。

【讨论】:

以上是关于该文档不存在,也不会出现在查询或快照中,但结构相同的文档有效的主要内容,如果未能解决你的问题,请参考以下文章

vmware vSphere克隆与快照技术

Firestore - 对文档使用更新方法,但使用对象(Java)

我经常在vs2010里调试C#网站程序,但 总报”当前不会命中断点,还没有为该文档加载任何符号。“不知道为什

在 Swift 中使用 AVAudioEngine 点击麦克风输入

Mailchimp电子邮件不会自动下载Outlook中的图像

如何忽略层次结构查询中特定类型的直接父级