假设我有以下情况:
我有多个活动,多个用户可以参加。此外,用户可以参加多个活动。在保持数据一致性的同时存储所需信息的最佳方法是什么?
这是我想出的,为什么我不喜欢它们:
collection "events" -> event document -> subcollection "users" -> user document
问题:
每个用户都存在于每个事件中,从而导致每个用户有多个文档。我不能只更新用户信息,因为我需要写到每个相关的事件文档并获取相关的用户文档。
如果尝试使读写次数最少,那真是一场灾难
例如:
this.afs.collection('events').get().then(res => {
res.forEach(document => {
document.ref.collection('users', ref => ref.where('name', '==', 'Will Smith')).get()
//Change name accordingly
})
})
collection "users" -> user document -> subcollection "events" -> event document
问题:
每个用户都存在每个事件,因此每个事件都有多个文档。 (与第一种情况相同,反之亦然)
collection "users" and collection "events"
,每个都有用户和事件作为从属于它们的文档。
有一个数组attending_events
,其中包含相关的事件ID。
问题:
SQL对事物进行排序的一种方式。需要使用forEach()
函数通过单独的查询来获取每个文档。
例如
this.afs.collection('events').doc(eventId).get().then(res => {
res.users.forEach(elem => {
this.afs.collection('users').doc(elem.name).get()
//Change name accordingly
})
})
我缺少什么,是否有更好的方法来对所需的架构进行建模?
答案 0 :(得分:1)
使用
collection "events" -> event document -> subcollection "users" -> user document
这并不像您想的那样糟糕。这种做法称为非规范化,是涉及Firebase的常见做法。如果您不熟悉NoSQL数据库,建议您观看以下视频Denormalization is normal with the Firebase Database,以更好地理解。它适用于Firebase实时数据库,但对于Cloud Firestore适用相同的规则。
我希望能够更改用户信息或事件信息而无需获取数百个文档。
如果您认为用户详细信息会经常更改,则应考虑在每个user
对象下存储array
个事件ID,并且不使用子集合。同样,您还应该在每个event
对象下添加一个array
的UID。您的新架构应如下所示:
Firestore-root
|
--- users (collection)
| |
| --- uid (document)
| |
| --- events: ["evenIdOne", "evenIdTwo", "evenIdThere"]
| |
| --- //Other user properties
|
--- events (collection)
|
--- eventId (document)
|
--- users: ["uidOne", "euidTwo", "uidThere"]
|
--- //Other event properties
由于仅保留引用,因此更改用户名后,无需在events
子集合中存在的所有用户对象中更新引用。但是请记住,在这种方法中,要获取例如某个用户的所有事件,您应该创建两个查询,一个查询从用户文档中获取事件ID,第二个查询基于这些事件ID获取事件文档。
基本上,这是在使用非规范化和在数组中存储数据之间的权衡。
在保持数据一致性的同时存储所需信息的最佳方法是什么?
通常,我们根据要执行的查询创建数据库模式。有关更多信息,我还建议您从以下帖子中查看答案: