I have a backend on firebase and there are something like post like in Facebook. So I need functionality liking these posts. The question is how to store likes and user who liked the post? All help will be appreciated
-
@luk2302 I just want to know how it would be theoretically. I don't need a code – Zhanserik Kenes Dec 21 '15 at 08:13
-
1The same logic applies to "theoretical" question: what thoughts and concepts have you come up with on your own yet? – luk2302 Dec 21 '15 at 08:14
-
@luke2302 Each post has a field, where I can store likes as array of objects – Zhanserik Kenes Dec 21 '15 at 08:18
-
@luke2302 I thought there is a better way to do that – Zhanserik Kenes Dec 21 '15 at 08:20
-
2Please edit that into your question so everybody can see it easily - I personally have no idea about firebase, just trying to improve your question so the chances are higher for you getting a helpful answer. – luk2302 Dec 21 '15 at 08:22
3 Answers
Take this data structure:
{
"posts": {
"post_1": {
"uid": "user_1",
"title": "Cool Post"
},
"post_2": {
"uid": "user_1",
"title": "Another Cool Post"
},
"post_3": {
"uid": "user_2",
"title": "My Cool Post"
}
},
"postLikes": {
"user_1": {
"post_3": true
},
"user_2": {
"post_1": true,
"post_2": true
}
}
}
The location /posts
retrieves all the posts.
The location /postLikes
retrieves all the likes on posts.
So let's say you're user_1
. To get the posts user_1
has liked you could write this Firebase database listener:
let ref = Firebase(url: "<my-firebase-app>")
let uid = "user_1"
let userRef = ref.childByAppendingPath(uid)
userRef.observeEventType(.Value) { (snap: FDataSnapshot!) in
print(snap.value) // prints all of the likes
// loop through each like
for child in snap.children {
let childSnap = child as! FDataSnapshot
print(childSnap.value) // print a single like
}
}
What's important to note here is the "flatness" of the data structure. The postLikes
are not stored under each post
. This means that you can retrieve a post
without getting all of its likes. But, if you want to get both, you can still do that since you know the user's id.
Try giving the Firebase guide on Structuring Data a read through

- 1,793
- 15
- 12

- 31,526
- 6
- 67
- 82
-
Thank you, David. One more question, how to fetch number of likes of post? – Zhanserik Kenes Dec 22 '15 at 07:54
-
1With the snapshot, you can access `snap.childrenCount`. However, this just a count of all the data downloaded. There isn't a way to just return the count. – David East Dec 22 '15 at 12:19
-
Not sure, it's really hard for me :). In your answer I can store likes, but can't count how many times the post was liked. Or I didn't understand something – Zhanserik Kenes Dec 23 '15 at 17:38
-
1You could also keep a "likeCount" within each post. When the client "likes" a post, you could increment that value client-side and push it back to the post. Make sure to handle race conditions though. – Josh Jan 13 '16 at 21:08
-
@DavidEast hello, David. If I'm using ur technology of fan-out. Should i store likes count in each post and on each like update likes count in each post on server side? Or It's better to store it as another node? and for each post get likes count from this node? – Vlad Pulichev Jul 20 '17 at 08:16
-
@Josh I'm currently facing this issue, how do you avoid race conditions in such a scenario? – SagunKho Oct 08 '17 at 04:26
-
"user_1" is stored as a document inside "postLikes" collection, which will work fine for a small number of likes but if likes are in millions, will this approach work? – Abdullah Khan Nov 18 '21 at 10:00
To add to the comments in david's answer, above (I can't add a comment yet) to get the count for likes, you want to use transactional data.
In your firebase, you want to set up a "likes" child, looks something like this in the post node:
{
"posts": {
"post_1": {
"uid": "user_1",
"title": "Cool Post"
"likes": 0
},
"post_2": {
"uid": "user_1",
"title": "Another Cool Post"
"likes": 0
},
"post_3": {
"uid": "user_2",
"title": "My Cool Post"
"likes": 0
}
The code in Xcode looks something similar to below. You would be adding a counter every time the post is liked (same code, but use "- 1" to unlike).
self.databaseRef.child("posts").child("post_1").child("likes").runTransactionBlock({
(currentData:FIRMutableData!) in
var value = currentData.value as? Int
//check to see if the likes node exists, if not give value of 0.
if (value == nil) {
value = 0
}
currentData.value = value! + 1
return FIRTransactionResult.successWithValue(currentData)
})
Hope this helps someone!
Additional reading for this sort of counter:
-
-
yes--to downvote/unlike run similar code but currentData.value = value! - 1 – gk103 Oct 07 '16 at 00:05
i think the best way to store likes is to create an array variable...then push their uid... if they unlike just pull out their uid... the size of the array will be the numbers of likes. this way you will have no duplicates.
"post_1": {
"uid": "user_1",
"title": "Cool Post"
"likes": []
}
post_1.likes.push(user.uid)

- 21
- 4