linus_hologram
linus_hologram

Reputation: 1705

Firestore Social Media Model Structure

I have a posts collection in which my application stores all the posts of a user, with the following data structure:

+ uid (the user id of the creator)
+ text-content : String
+ tagged-users: [String]
+ assigned-media: [{"downloadUrl": String, "storageLocation": String}]
+ type: String
+ typestamp: Timestamp
+ Likes
    + uid (the user id of the liking person)
    + timestamp: Timestamp
    + postId (optional, depending on the results of the collection group queries)

Now, I would like to display all the posts of this collection to my user; but only, if the user follows the person who created the post, i.e the uid field of the post document fits.

I know that it is simple to query the collection if the user only follows one person, i.e. I have one simple where clause. But: What if my user follows 10.000 people or more? How can I query that?

Also, how should I store the followings, i.e. the persons a user follows? Using a simple array doesn't seem suitable for me, but with all the other options I can't query the posts collection for posts that come from a person I follow.

I would be grateful for every help I could get!

Upvotes: 5

Views: 2155

Answers (1)

andresmijares
andresmijares

Reputation: 3744

This is a kind of complex question (and I'm not 100% sure that this is the right place to ask for it), I will do my best to come with something to get you started,

Disclaimer, this might or not for your use case

Divide your service into 3 collections: - users - followers - posts

users Collection is very straight forward, you just need the document id (you already have it).

{
  "andyIsTheBest": {
    uid: `andyIsTheBest`
    // ...
  },
  "sophieTheBest": {
     uid: `sophieTheBest`,
     // ...
   },
   "andyTheWorst": {
     uid: `andyTheWorst`,
     // ...
   },
}

followers mirror the user's docs id, it should look like this:

{
  "andyIsTheBest": {
     last_post: 2019,
     followers: [
       'sophieTheBest', 'andyTheWorst'
     ],
     recent: [
       {
         post_id: 112233, // from the post collection
         seq: 2019
       }
     ]
  }
}

Finally, the posts collection looks something like this:

{
   "112233": {
     seq: 2019,
     body: `blabla the cool post`
     author: `andyIsTheBest`
   }
}

Important, notice the sequence seq number also the last_post, you can update this value via cloud functions so you keep track of it, then the rest are just implementations details:

const remove = firebase.firestore.FieldValue.arrayRemove
const union = firebase.firestore.FieldValue.arrayUnion

const follow = async (toFollow, user) => {
    await db
    .collection('followers')
    .doc(toFollow)
    .update({ users: union(user) });
}

const unfollow  = async (toUnFollow, user) => {
    await db
    .collection('followers')
    .doc(toUnFollow);
    .update({ users: remove(user) });
}

const feed = async (user) => {
   await db.collection(`followers`)
      .where(`followers`, `array-contains`, user)
      .orderBy(`last_post`, `desc`)
      .limit(10)
      .get()

   // do whatever business logic you need down here
}

Basically this way, it doesn't matter if you have 1 or 1 Trillion, the queries should be ok.

There are a lot of details I didn't cover but this should be ok to get you started.

Hope this help.

Credits to my coworkers who implemented this at my company ^^

Upvotes: 3

Related Questions