user2637946
user2637946

Reputation:

Firebase query order

I have multiple posts and each post have it's own comments. I want to query all posts, ordered by their time stamps. I tried:

let query = Firebase(url: path)
let query.queryOrderedByChild("commentDate").observeEventType(.ChildAdded)
 { (queryResponse, cancelBlock) { ....

"commentDate" are integers on server. At this query I get only the first object

let query = Firebase(url: path)
query.queryOrderedByChild("commentDate").queryLimitedToFirst(100).observeEventType(.ChildAdded) { (queryResponse, cancelBlock) { ...

I get only the first object as well... The single solution I have at the moment is to query all :

 query.queryOrderedByChild("commentDate").observeEventType(.Value) { (queryResponse, cancelBlock) in ...

But using this I must sort the array before showing to user.

Any ideas how can I do to get them sorted on server?

Edit Representation of firebase data:

{
  "-KGRZmSIDXz5hHkelthQ" : {
    "something1" : "783151",
    "something2" : "21",
    "something3" : "wjeicisje ejej",
    "comments" : "",
  },
  "-KGRa5skGzA1GAG09Lno" : {
    "something1" : "783151",
    "something2" : "21",
    "something3" : "wjeicisje ejej",
    "comments" : "",
  },
  "-KGVr-tti1zr1M1QLlHL" : {
    "something1" : "783151",
    "something2" : "21",
    "something3" : "wjeicisje ejej",
    "comments" : {
      "-KGX1_rFSBLmQJ7QzCRc" : {
        "commentBody" : "something",
        "commentDate" : 1.461933727259896E9,
        "commentOwnerImageView" : "something",
        "commentOwnerName" : "something"
      },
      "-KGX1r5Lnhv9YbQre6as" : {
        "commentBody" : "something",
        "commentDate" : 1.461933797884702E9,
        "commentOwnerImageView" : "something",
        "commentOwnerName" : "something"
      },
      "-KGXVGKA0SYm-vRs6zsv" : {
          "commentBody" : "something",
        "commentDate" : 1.461941507496439E9,
        "commentOwnerImageView" : "something",
        "commentOwnerName" : "something"
      },
    },
  }
}

Upvotes: 0

Views: 1712

Answers (2)

Jay
Jay

Reputation: 35677

Your data structure looks fine, so a simple query will return the results you want

let commentsRef = ref.childByAppendingPath("-KGVr-tti1zr1M1QLlHL/comments")

commentsRef.queryOrderedByChild("commentDate").observeEventType(.ChildAdded, withBlock: {
  snapshot in

  let nodeData = snapshot.value
  print(nodeData!)

})

The above will return each child node, one at a time in the proper order.

If you have a small amount of nodes, you can just read them in at one time and iterate over the snapshot.children like this

usersRef.queryOrderedByChild("commentDate").observeEventType(.Value, withBlock: {
  snapshot in

  for child in snapshot.children {
    print(child)
  }

})

Both of the above will print out each comment node ordered by commentDate

The above will work only if you are interested in retrieving the comments within each post. If not, you'll need to change your Firebase structure and move the comments to separate node, like this

posts
   post_01
   post_02
   etc

and a separate comments node that's refers to the post the comment belongs to. Since you want to query for say the comments for post_02, and want them ordered by commentDate, combine the post number and date into a single child.

comments
   "-KGX1_rFSBLmQJ7QzCRc" : {
     "for_post_and_commentDate": "post_02_1.461933727259896E9",
     "commentBody" : "something",
     "commentOwnerImageView" : "something",
     "commentOwnerName" : "something"
   },
   "-KGX1r5Lnhv9YbQre6as" : {
     "for_post_and_commentDate": "post_02_1.461933797884702E9",
     "commentBody" : "something",
     "commentOwnerImageView" : "something",
     "commentOwnerName" : "something"
     },

and then modify the query

usersRef.queryOrderedByChild("for_post_and_commentDate")
   queryStartingAtValue("post_02_0").queryEndingAtValue("post_02_xxx").observeEventType(.Value, withBlock: {

You'll have to figure out your commentDate format as it would be easier to craft starting and ending timestamps if they were stored: 20160430100621 as a yyyymmddhhmmss format, then your timestamps could be queried like this:

starting: post_02_0
ending: post_02_99999999999999

This also gives you the flexibility to query for comments for post_02 that happened yesterday, or last week.

Upvotes: 1

Frank van Puffelen
Frank van Puffelen

Reputation: 600130

Firebase can query nested children if you know the entire path (so something like dimensions/length). It cannot handle dynamic elements in that path under each child (like your $commentid/commentDate).

The only way to get this working is to pull the necessary data up to a level where you can query it. For example, if you keep track of the lastCommentDate for each blog post:

{
  "-KGRZmSIDXz5hHkelthQ" : {
    "something1" : "783151",
    "something2" : "21",
    "something3" : "wjeicisje ejej",
    "comments" : "",
  },
  "-KGRa5skGzA1GAG09Lno" : {
    "something1" : "783151",
    "something2" : "21",
    "something3" : "wjeicisje ejej",
    "comments" : "",
  },
  "-KGVr-tti1zr1M1QLlHL" : {
    "something1" : "783151",
    "something2" : "21",
    "something3" : "wjeicisje ejej",
    "firstCommentDate": 1.461933727259896E9,
    "lastCommentDate": 1.461941507496439E9,
    "comments" : {
      "-KGX1_rFSBLmQJ7QzCRc" : {
        "commentBody" : "something",
        "commentDate" : 1.461933727259896E9,
        "commentOwnerImageView" : "something",
        "commentOwnerName" : "something"
      },
      "-KGX1r5Lnhv9YbQre6as" : {
        "commentBody" : "something",
        "commentDate" : 1.461933797884702E9,
        "commentOwnerImageView" : "something",
        "commentOwnerName" : "something"
      },
      "-KGXVGKA0SYm-vRs6zsv" : {
          "commentBody" : "something",
        "commentDate" : 1.461941507496439E9,
        "commentOwnerImageView" : "something",
        "commentOwnerName" : "something"
      },
    },
  }
}

With this structure you can query blog posts by their last comment date:

ref.orderByChild('lastCommentDate').limitToLast(10).on(...

Upvotes: 1

Related Questions