Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best practice of firestore data structure?

I'm making a blog app using firebase.

I want to know the best practice of data structure.

As far as I know, there are 2 case. (I'm using react native)

case 1:

posts
  -postID
   -title,content,author(userID),createdDate,favoriteCount

favorites
  -userID
    -favoriteList
      -postID(onlyID)
      -postID(onlyID)

In this case, for example, when we need to get favorite posts.

firebase.firestore().collection(`favorites/${userID}/favoriteList`)
    .get()
    .then((snapshot) => {
      snapshot.forEach((favorite) => {
        firebase.firestore().collection(`favorites/`).doc(`${favorite.id}`)
          .get()
          .then((post) => {
          myPostList.push(post.data())
        });
  });

in this case, we can't order the favorite posts by createdDate. So, need to sort client side. Even if so, we don't use limit() function.

case 2:

posts
  -postID
  -title,content,author(userID),createdDate,favoriteCount

favorites
  -userID
     -favoriteList
       -postID
         -title,content,author(userID),createdDate,favoriteCount
       -postID
         -title,content,author(userID),createdDate,favoriteCount

firebase.firestore().collection(`favorites/${userID}/favoriteList`).orderBy('createdDate','desc').limit(30)
    .get()
    .then((snapshot) => {
      snapshot.forEach((post) => {
        myPostList.push(post.data())
      });
  });

in this case, When the favorite post is modified by the author, we have to update all of the favorite posts. (e.g. If 100 users save the post as a favorite, we have to update to 100 data.)

(And I'm not sure we can increment favoritecount by a transaction, exactly same.)

I think if we use firebase.batch(), we can manage it. But I think it seems Inefficient.

It seems that both ways are not perfect. Do you know the best practice of this case?

like image 480
yn1043 Avatar asked Feb 06 '18 20:02

yn1043


People also ask

What is the correct firebase database structure?

All Firebase Realtime Database data is stored as JSON objects. You can think of the database as a cloud-hosted JSON tree. Unlike a SQL database, there are no tables or records. When you add data to the JSON tree, it becomes a node in the existing JSON structure with an associated key.

What is the primary format for storing data in firestore?

Cloud Firestore is a NoSQL, document-oriented database. Unlike a SQL database, there are no tables or rows. Instead, you store data in documents, which are organized into collections. Each document contains a set of key-value pairs.

Why is firestore the best?

Firestore is Very Scaleable Without getting too technical, Firestore bakes in a lot of best practices when it comes to running a scalable database so developers don't have to. Since Firestore is backed by Google Cloud Platform, you can rest assured that your database can scale to meet your needs.


1 Answers

What about using arrays or Collection Groups?

solution 1: arrays

posts
  -postID
   -title,content,author(userID),createdDate,favoriteCount
  -[favoriters(userID)]

Now you can query for a user's favorites by querying posts that "array-contains" the user's ID. You can also modify individual posts without iterating through a bunch data copies.

There's a limit to this approach though. Maximum size for a document is 1 MiB; assuming that a user ID is 4 bytes, a document can contain no more than 250K favoriters. Clients would also have to do some O(N) processing to add / remove favoriters.

solution 2: Collection Groups

posts
  -postID
   -title,content,author(userID),createdDate,favoriteCount
  -favoriters {collection}
   -userID

A collection group consists of all collections with the same ID. By default, queries retrieve results from a single collection in your database. Use a collection group query to retrieve documents from a collection group instead of from a single collection.

So we can fetch a user's favorite posts via

db.collectionGroup("favoriters").whereEqualTo("userID", <userID>).get();

To favorite a post, we just do

const postsRef = db.collection("posts");
postsRef.document(<postID>).collection("favoriters").add({ "userID", <userID> });
like image 119
Gilbert Avatar answered Oct 04 '22 17:10

Gilbert