13

I'm building a social app using Firebase. I store posts in Firebase like this:

posts: {
   "postid": {
      author: "userid" 
      text: "",
      date: "timestamp"
      category: "categoryid"
      likes: 23
   }
}

Each post belong to a category and it's possible to like posts.

Now, I'm trying to show posts that belong to a specific category, sorted by the number of likes. It's possible I also want to limit the filter by date, to show only the most recent, most liked posts in a category. How can I do this?

Firebase query functionality doesn't seem to support multiple queries like this, which seems strange...

rodskagg
  • 3,827
  • 4
  • 27
  • 46
  • See http://stackoverflow.com/questions/26700924/query-based-on-multiple-where-clauses-in-firebase – Kato Sep 26 '16 at 23:30

1 Answers1

14

You can use only one ordering function with Firebase database queries, but proper data structure will allow you to query by multiple fields.

In your case you want to order by category. Rather than have category as a property, it can act as an index under posts:

posts: {
   "categoryid": {
       "postid": {
         author: "userid" 
         text: "",
         date: "timestamp",
         category: "categoryid",
         likes: 23
       }
   }
}

Now you can write a query to get all the posts underneath a specific category.

let postsRef = Firebase(url: "<my-firebase-app>/posts")
let categoryId = "my-category"
let categoryRef = postsRef.childByAppendingPath(categoryId)
let query = categoryRef.queryOrderedByChild("date")
query.observeEventType(.ChildAdded) { (snap: FDataSnapshot!) {
  print(snap.value)
}

The code above creates a reference for posts by a specific category, and orders by the date. The multiple querying is possible by the data structure. The callback closure fires off for each individual item underneath the specified category.

If you want to query further, you'll have to do a client-side filtering of the data.

David East
  • 31,526
  • 6
  • 67
  • 82
  • 1
    Thanks for the reply! That sort of could work, but I'm saving references to the posts (only storing the ID of the post) in other locations (for example in user's feeds etc). Using the solution you suggest, it would be impossible to get the actual post data using only the post ID, as I would need the category ID as well, to "drill down" to the correct node... Because as far as I know it's not possible to use wildcards (*) in paths when querying the database, such as /posts/*/[postid] ? – rodskagg Dec 05 '15 at 13:18
  • 1
    One solution is of course to store the category a post belongs to in another node, such as /category_for_post/[postid]/[categoryid] but that means I will have to do an additional query for this info everytime I want to get the actual data for a post. – rodskagg Dec 05 '15 at 13:21
  • @andlin: Yes, you can also store categories like "tags" and search by those tags. You can still follow the structure above, but call it `/categoryPosts` and then store all the posts in `posts`. It's okay to duplicate the data because it will lead to faster reads and you can keep it consistent with client-side fanout. https://www.firebase.com/blog/2015-10-07-how-to-keep-your-data-consistent.html – David East Dec 05 '15 at 14:27
  • 1
    @DavidEast is there any way to order by likes with pagination. – iDhaval May 05 '17 at 10:41
  • Hi everyone. Follow David East's structure on Firebase. Is there any way to order by likes with pagination? Or Is there any way to get all posts with pagination? – HuyLe Mar 19 '18 at 03:12