我有一个基于文档的数据结构,里面充满了用户。关于用户的信息将包括每周议程(一周内要做的活动,例如:周一运行10分钟,周二购物),以及其他基本信息,如他们的名字、性别、年龄等。用户可以有多个每周议程(例如,一个是本周的,另一个是下周的,等等)
然而,我不知道如何构建这些数据。
如果用户目录中有两个子目录,一个子目录名为"weekly_agendas"(包含用户所有每周议程的文档),另一个子目录名称为"user_data",包含姓名、性别、年龄等个人信息。本质上,嵌套数据正在创建中。
或:
是否应将"weekly_agendas"目录移到用户目录之外?
我在谷歌上搜索过所有地方,所有文档通常都建议防止嵌套数据结构,但这种嵌套数据结构怎么会不好呢?
这有助于说明我想要达到的目标:
Structure #1
users
|
+--user_id
|
+--user_data
|
+--username
+--age
+--gender
+--weekly_agenda
|
+--weekly_agenda_number
|
+--1: walk the dog on Monday
+--2: Go shopping on Tuesday
Structure #2:
users
|
+--user_id
|
+--username
+--age
+--gender
+--weekly_agenda
|
+--user_id
|
+--weekly_agenda_number
|
+--1: walk the dog on Monday
+--2: Go shopping on Tuesday
(为了将来参考,这种类型的"最佳实践"问题比Stack Overflow更适合Firebase Google Group)
首先,我不确定这是故意的还是图表中的错误,但我只想指出,在Structure#1中,应该将username
、age
和gender
作为用户文档中的字段,而不是像图表所示的那样作为子集合。(考虑到你的描述,我猜这就是你的意思,但只是为了确定,因为用户数据对子集合的使用会很差)。
现在谈谈你的主要问题:
Firestore在平面数据结构上操作时受益匪浅,即具有大量小文档而不是少量大文档的数据结构。这是人们在谈论反嵌套实践时提到的要点之一。
如何构建数据完全取决于计划如何与之交互,而不仅仅是查看数据的意义。
如果您计划让用户能够看到其他用户的议程,那么Structure #1
将无法像Structure #2
那样工作。它仍然可以工作,但查询将更加丑陋。
也就是说,如果议程只对其所有者可见,那么Structure #1
可能更有意义,因为组织对该目标更直观。使用Structure #1
,您可能会体验到稍微更快的查询响应时间。
Structure #2
没有任何问题。如果现在或将来,用户可以查看其他用户的议程,那么Structure #2
是你的最佳选择。如果你计划根据其中一个字段在多个用户中搜索议程,Structure #2
也会更好。例如,如果您想按timestamp
字段查找20个最新的应用程序范围议程文档。
我的项目有一个非常相似的情况,有不同的背景。我们的应用程序有Posts
和Content
。每个CCD_ 14包含一个或多个CCD_。我们本可以将Content
作为每个Post
的子集合(如您的Structure #1
),但我们将Content
作为根级别集合(如Structure #2
),因为我们需要根据用户的某个字段跨用户查询Content
文档。
总之,Structure #2
更灵活,但如果您确定不想跨多个用户查询议程(集合组查询),那么Structure #1
可能更有利。
我通常默认为Structure #2
,除非在那些罕见但合法的情况下,将数据隔离到特定文档确实更有意义。
构建Cloud Firestore数据库没有"完美"、"最好"或"正确"的解决方案。
我在谷歌上搜索过所有地方,所有文档通常都建议防止嵌套数据结构,但这种嵌套数据结构怎么会不好呢?
与Firebase实时数据库中显示每周议程列表不同,您可能已经下载了整个用户对象,在Cloud Firestore中,这不再是问题。因此,在每个用户文档下嵌套一个名为weekly_agenda
的子集合不会成为问题。第一种方法的缺点是,您不能查询数据库来显示所有用户的所有议程。因此,一个可能的方案,即您的解决方案的混合方案可能是:
Firestore-root
|
--- users (collection)
| |
| --- uid (document)
| |
| --- username: "John"
| |
| --- age: 22
| |
| --- gender: "male"
|
--- weeklyAgenda (collection)
|
--- weeklyAgendaId (document)
|
--- uid: "UidOfTheUser"
|
--- //Weekly Agenda Properties
使用此模式,您可以简单地:
- 通过在
users
集合上附加侦听器来查询整个数据库中的所有用户 - 通过在
weeklyAgenda
集合上附加一个监听器来查询所有用户的议程 通过使用在Android中可能看起来像这样的查询来查询属于单个用户的所有议程:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance(); Query query = productsRef.whereEqualTo("uid", uid);
此查询也可以用其他编程语言编写。