Firebase efficiently model nXn relationship

你说的曾经没有我的故事 提交于 2020-01-22 02:19:09

问题


Let's say I have the following scenario:

I have multiple events, that multiple users can attend. Also, users can attend multiple events. What's the best way of storing the required information with maintaining data consistency?

Here's what I came up with and why I don't really fancy them:

collection "events" -> event document -> subcollection "users" -> user document Problem: Each user exists on each event, resulting in multiple documents of each user. I can't just update user information as I would need to write to every relevant event document and fetch the relevant user documents. Really a disaster if trying to make the least reads/writes possible E.g.:

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 Problem: Each event exists on each user, resulting in multiple documents of each event. (Same problem as in the first scenario, just the other way around)

collection "users" and collection "events" with each having users and events as documents subordinate to them. There's an array attending_events which has the relevant event id's in it. Problem: Kind of the SQL way of sorting things. There's the need of getting each document with a seperate query using a forEach() function. E.g.

this.afs.collection('events').doc(eventId).get().then(res => {
    res.users.forEach(elem => {
        this.afs.collection('users').doc(elem.name).get()
        //Change name accordingly
    })
})

What am I missing, is there better approaches to model the desired architecture?


回答1:


When using collection "events" -> event document -> subcollection "users" -> user document

It's not so bad as you might think. This practice is called denormalization and is a common practice when it comes to Firebase. If you are new to NoSQL databases, I recommend you see this video, Denormalization is normal with the Firebase Database for a better understanding. It is for Firebase realtime database but the same rules apply in the case of Cloud Firestore.

I want to be able to change user information or event information without the need of fetching hundreds of documents.

If you think that user details will be changed very often, then you should consider storing under each user object an array of event IDs and not use a subcollection. In the same way, you should also add under each event object an array of UIDs. Your new schema should look like this:

Firestore-root
   |
   --- users (collection)
   |    |
   |    --- uid (document)
   |         |
   |         --- events: ["evenIdOne", "evenIdTwo", "evenIdThere"]
   |         |
   |         --- //Other user properties
   |
   --- events (collection)
        |
        --- eventId (document)
             |
             --- users: ["uidOne", "euidTwo", "uidThere"]
             |
             --- //Other event properties

Since you are holding only references, when the name of a user is changed, there is no need to update it in all user objects that exist in events subcollection. But remember that in this approach, to get for example all events a user is apart off, you should create two queries, one to get the event IDs from user document and second to get event documents based on those event IDs.

Basically it's a trade-off between using denormalization and storing data in arrays.

What's the best way of storing the required information with maintaining data consistency?

Usually, we create the database schema according to the queries we intend to perform. For more infos, I also recommend to see my answer from the following post:

  • What is the correct way to structure this kind of data in Firestore?


来源:https://stackoverflow.com/questions/58818379/firebase-efficiently-model-nxn-relationship

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!