Ham*_*son 5 firebase google-cloud-firestore
我的应用程序用户集合中的每个文档都有一个子集合。该子集合存储与用户相关的文档,但是也可以将它们保存到主集合中,每个文档都具有关联的userId。
我选择了这种结构,因为它在当时似乎最为明显,但是我可以想象,如果我需要进行数据库维护,它将使事情变得更加艰难。例如,如果要清理这些文档,则必须先查询每个用户,然后再查询每个用户的文档,而如果我拥有主集合,则可以查询所有文档。
That lead me to question what is the point of subcollections at all, if you can just associate those docs with an ID. Is it solely there so that you can expand if your doc becomes close to the 1MB limit?
让我们举个例子。假设我们有一个测验应用程序的数据库架构,如下所示:
Firestore-root
|
--- questions (collections)
|
--- questionId (document)
|
--- questionId: "LongQuestionIdOne"
|
--- title: "Question Title"
|
--- tags (collections)
|
--- tagIdOne (document)
| |
| --- tagId: "yR8iLzdBdylFkSzg1k4K"
| |
| --- tagName: "History"
| |
| --- //Other tag properties
|
--- tagIdTwo (document)
|
--- tagId: "tUjKPoq2dylFkSzg9cFg"
|
--- tagName: "Geography"
|
--- //Other tag properties
Run Code Online (Sandbox Code Playgroud)
其中tags是questionId对象内的子集合。现在让我们将tags集合创建为顶级集合,如下所示:
Firestore-root
|
--- questions (collections)
| |
| --- questionId (document)
| |
| --- questionId: "LongQuestionIdOne"
| |
| --- title: "Question Title"
|
--- tags (collections)
|
--- tagIdOne (document)
| |
| --- tagId: "yR8iLzdBdylFkSzg1k4K"
| |
| --- tagName: "History"
| |
| --- questionId: "LongQuestionIdOne"
| |
| --- //Other tag properties
|
--- tagIdTwo (document)
|
--- tagId: "tUjKPoq2dylFkSzg9cFg"
|
--- tagName: "Geography"
|
--- questionId: "LongQuestionIdTwo"
|
--- //Other tag properties
Run Code Online (Sandbox Code Playgroud)
这两种方法之间的差异是:
tags特定问题,则使用第一个模式非常简单,因为只CollectionReference需要一个(问题-> questionId->标记)。要使用第二个模式实现相同的目的,而不是a CollectionReference,Query则需要a,这意味着您需要查询整个tags集合以仅获取与单个问题对应的标签。这项技术称为数据库扁平化,是Firebase的一种非常普遍的做法。因此,仅在需要时才使用此技术。因此,在您的情况下,如果只需要显示单个问题的标签,请使用第一个模式。如果您想以某种方式显示所有问题的所有标签,则建议使用第二种模式。
它是否仅存在于其中,以便您的文档接近1MB的限制时可以扩展?
如果文档中有对象的子集合,请注意,该子集合的大小不计入该1 MiB限制。仅计算存储在文档属性中的数据。
编辑2019年10月1日:
根据@ShahoodulHassan的评论:
因此,您无法使用第一个模式获取所有问题的所有标签吗?
实际上,现在有了Firestore集合组查询,我们可以获得所有问题的所有标签。要注意的一件事是,例如,所有子团队必须具有相同的名称tags。
我发现子集合的最大优点是它们有自己的写入速率限制,因为每个子集合都有自己的索引(假设您没有集合组索引)。对于小型应用程序来说,这可能不是问题,但对于中/大型应用程序来说,这可能非常重要。
想象一个聊天应用程序,其中每个聊天都有一系列消息。您需要按时间戳对消息进行索引,以便按时间顺序显示它们。Firestore 的顺序值写入限制为 500/秒,这对于中型应用程序来说绝对是可以承受的(特别是如果您考虑到流氓用户编写消息脚本的可能性——目前使用安全规则不容易阻止这种情况)
// root collection
/messages {
chatId: string
timeSent: timestamp // the entire app would be limited to 500/second
}
Run Code Online (Sandbox Code Playgroud)
// sub-collection
/chat/{chatId}/messages {
timeSent: timestamp // each chat could safely write up to 500/second
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
705 次 |
| 最近记录: |