最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - What is the best practice of firestore data structure? - Stack Overflow

programmeradmin1浏览0评论

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?

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?

Share Improve this question edited Jun 13, 2018 at 9:49 Adam Azad 11.3k5 gold badges30 silver badges72 bronze badges asked Feb 6, 2018 at 20:24 yn1043yn1043 5883 gold badges14 silver badges24 bronze badges 2
  • 2 You should structure your data in a way that best suits the queries you want to perform. – Doug Stevenson Commented Feb 6, 2018 at 20:36
  • @DougStevenson thank you for responding.hmm... I found It is case by case.thank you – yn1043 Commented Feb 7, 2018 at 9:36
Add a comment  | 

2 Answers 2

Reset to default 12

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> });

Maybe not a direct answer to your question, but the official documentation has an example for that:

Working with arrays, lists, and sets

Summary: Store and query data in array-like structures in documents.

Use case: If your app requires complex data objects like arrays, lists, or sets, follow the model outlined in this solution. For example, in a blogging app, you might want to create a set of related posts.

https://firebase.google.com/docs/firestore/solutions/arrays

发布评论

评论列表(0)

  1. 暂无评论