What is the best practice of firestore data structure?
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> });
![yn1043](https://i.stack.imgur.com/IrKXp.png?s=256&g=1)
yn1043
Updated on June 05, 2022Comments
-
yn1043 about 2 years
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?