Unenumrated
Unenumrated

Reputation: 349

Efficiently storing and getting likes in FireStore / Document DB

I have a page with posts and likes for each post.

In FireStore a collection of posts and a collection of likes, and I update the total_likes and recent likes array when a user likes or unlikes a post with cloud functions.

However, I can't figure out how to show for each post if the currently logged in user liked it or not. What's an efficient way to do that for.

Any pointers?

Upvotes: 3

Views: 5134

Answers (3)

LordeW
LordeW

Reputation: 1

You can save uid inside 'likes' sub-collection.

In your app create: if user have uid in this food, 'likes' sub-collection = do something (in my case user cant like this food)

I recomended for read: https://firebase.google.com/docs/firestore/manage-data/structure-data

this my way save data in firestore

Foods => City => 12.2029 => foodId => foodData => likes => userId;

Here how i save my likes "but i dont like how i save it" i still search better way.

all this code for tests "use it if your know how work firestore rules"

my Firestore rules for Foods collection :

    match /Foods/{cityName}/{monthYear}/{foodId} {
      // Allow read access for all authenticated users
      allow read: if request.auth != null;

      // Allow creation of a food item: only the restaurant owner or valid non-owner users can add food
      allow create: if request.auth != null && (getUserRole(request.auth.uid) == 'owner' || canAddFood(request.auth.uid));

      // Allow updates and deletion of a food item only by the restaurant owner
      allow update, delete: if request.auth != null && request.auth.uid == restaurantId(request.resource.data.restaurantId);
    }

Upvotes: 0

davidverweij
davidverweij

Reputation: 338

I believe you might need to look at data aggregration. Even though this example is with Angular, I also use the same principle in a different application: https://angularfirebase.com/lessons/firestore-cloud-functions-data-aggregation/

Alternatively, you could store the post_id's that your user likes in their own 'like_array'. Knowing which posts the user currently sees, you can cross reference the shown post_id's with the (single object) 'like_array' from the user to determine if he/she has liked a particular post. In the long run, you could disambiguate like_arrays based on days or weeks, and only query the like_arrays of this and last day/week - based on what post you are showing. If you are working with categories of posts, similar applies: different like_arrays for different categories.

Hope this helps!

Upvotes: 4

Renaud Tarnec
Renaud Tarnec

Reputation: 83093

One solution would be to have another collection in your Firestore database where you create a document by user, in which you save (and update) an object containing all the posts this user has liked.

Like

- likers    (Collection)
   - UserUID (doc)
      -  postIds {
             post1_UID: true,
             post2_UID: true 
         }

The idea is to use the technique described in the doc, here: https://firebase.google.com/docs/firestore/solutions/arrays#solution_a_map_of_values

I don't know which language you use in the front end but in JavaScript you would do:

var postToTestId = ....;  <- You set this value as you need (e.g. as a function parameter)
firebase.auth().signInWithEmailAndPassword("...", ".....")
    .then(function (info) {
        var postId = 'azer';
        return db.collection('likers')
            .where('postIds.'+ postToTestId, '==', true)
            .get();
    })
    .then(function(querySnapshot) {
        if (querySnapshot.size > 0) {
            console.log("USER LIKES THIS POST!!!");
        }
    })
    .catch(function (error) {
        console.log(error);
    });

I don't think there is any solution without storing somewhere all the posts each user liked...

Upvotes: 3

Related Questions