我的应用程序用户集合中的每个文档都有一个子集合。该子集合存储与用户相关的文档,但是也可以将它们保存到主集合中,每个文档都具有关联的userId。
我选择了这种结构,因为它在当时似乎最为明显,但是我可以想象,如果需要进行数据库维护,它将使事情变得更加艰难。例如。如果要清理这些文档,则必须先查询每个用户,然后再查询每个用户的文档,而如果我有一个主集合,则可以查询所有文档。
这使我质疑子集合的意义是什么,如果您可以将这些文档与ID相关联的话。仅仅是在那里,以便您的文档接近1MB限制时可以扩展吗?
答案 0 :(得分:4)
让我们举个例子。假设我们有一个测验应用程序的数据库架构,如下所示:
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
其中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
这两种方法之间的区别是:
tags
,则使用第一个模式非常简单,因为只需要一个CollectionReference
(问题-> questionId->标记)。要使用第二个模式来实现相同的目的,需要一个CollectionReference
来代替Query
,这意味着您需要查询整个tags
集合以仅获取对应的标签一个问题。此技术称为数据库展平,在Firebase中是一种非常普遍的做法。因此,仅在需要时才使用此技术。因此,在您的情况下,如果只需要显示单个问题的标签,请使用第一个模式。如果您想以某种方式显示所有问题的所有标签,则建议使用第二种模式。
它是否仅存在于其中,以便您的文档接近1MB的限制时可以扩展?
如果文档中有对象的子集合,请注意,该子集合的大小不计入该1 MiB限制。仅计算存储在文档属性中的数据。
答案 1 :(得分:0)
子集合唯一潜在的技术优势与文档大小有关-它使您可以省略对父元素的引用。 (即,对于每个相关的rootDocument -> subCollection
,从根集合文档到子集合只有一个指针)。
/messages
|
--> /messages/tags
如果tags
是子集合,则它们不需要保存messageId
,因为您可以通过消息文档访问标签:
collection("messages").document(messageId).collection("tags")
/messages
/tags
使用根tags
集合,每个标签都需要存储messageId
。基本上,这会改变指针的方向。
collection("tags").whereEqualTo("messageId", messageId)
子集合:指针来自one -> many
根集合:指针来自many -> one
答案 2 :(得分:0)
令人惊讶的是之前没有提到过,但是子集合可以(在某些情况下)帮助绕过 orderBy 限制:
<块引用>您不能按包含在等式 (==) 或 in 子句中的字段对查询进行排序。
假设您想获取用户最近 10 次登录:
顶级:
//We can't use .orderBy after .where('==')
USER_LOGINS.where('userId', '==', {uid}).limit(10)
子集合:
//With a subcollection we can order and limit properly
USERS.doc({uid}).collection('LOGINS').orderBy('unixCreated', 'desc').limit(10);