christostsang
christostsang

Reputation: 1841

Cloud Firestore and data modeling: From RDBMS to No-SQL

I am building an iOS app that is using Cloud Firestore (not Firebase realtime database) as a backend/database.

Google is trying to push new projects towards Cloud Firestore, and to be honest, developers with new projects should opt-in for Firestore (better querying, easier to scale, etc..).

My issue is the same that any relational database developer has when switching to a no-SQL database: data modeling

I have a very simple scenario, that I will first explain how I would configure it using MySQL:

I want to show a list of posts in a table view, and when the user clicks on one post to expand and show more details for that post (let say the user who wrote it). Sounds easy.

In a relational database world, I would create 2 tables: one named "posts" and one named "users". Inside the "posts" table I would have a foreign key indicating the user. Problem solved.

enter image description here

Poor Barry, never had the time to write a post :(

Using this approach, I can easily achieve what I described, and also, if a user updates his/her details, you will only have to change it in one place and you are done.

Lets now switch to Firestore. I like to think of RDBMS's table names as Firestore's collections and the content/structure of the table as the documents.

In my mind i have 2 possible solutions:

Solution 1:

Follow the same logic as the RDBMS: inside the posts collection, each document should have a key named "userId" and the value should be the documentId of that user. Then by fetching the posts you will know the user. Querying the database a second time will fetch all user related details.

Solution 2:

Data duplication: Each post should have a map (nested object) with a key named "user" and containing any user values you want. By doing this the user data will be attached to every post it writes.

Coming from the normalization realm of RDBMS this sounds scary, but a lot of no-SQL documents encourage duplication(?).

The only benefit I see in the second solution is that you can fetch both post and user data in one call.

Is there any other solution for this simple yet very common scenario?

ps: go easy on me, first time no-sql dev.

Thanks in advance.

Upvotes: 9

Views: 2025

Answers (2)

Puches
Puches

Reputation: 135

@christostsang I would suggest a combination of option 1 and option 2. I like to duplicate data for the view layer and reference the user_id as you suggested.

For example, you will usually show a post and the created_by or author_name with the post. Rather than having to pay additional money and cycles for the user query, you could store both the user_id and the user_name in the document.

A model you could use would be an object/map in firestore here is an example model for you to consider

posts = {
  id: xxx,
  title: xxx,
  body: xxx,
  likes: 4,
  user: {refId: xxx123, name: "John Doe"}
}

users = {
  id: xxx,
  name: xxx,
  email: xxx,
}

Now when you retrieve the posts document(s) you also have the user/author name included. This would make it easy on a postList page where you might show posts from many different users/authors without needed to query each user to retrieve their name. Now when a user clicks on a post, and you want to show additional user/author information like their email you can perform the query for that one user on the postView page. FYI - you will need to consider changes that user(s) make to their name and if you will update all posts to reflect the name change.

Upvotes: 0

Nth.gol
Nth.gol

Reputation: 844

Use solution 1. Guidance on nesting vs not nesting will depend on the N-to-M relationship of those entities (for example, is it 1 to many, many to many?).

If you believe you will never access an entity without accessing its 'parent', nesting may be appropriate. In firestore (or document-based noSQL databases), you should make the decision whether to nest that entity directly in the document vs in a subcollection based on the expect size of that nested entity. For example, messages in a chat should be a subcollection, as they may in total exceed the maximum document size.

Mongo, a leading noSQL db, provides some guides here Firestore also provided docs Hope this helps

Upvotes: 2

Related Questions