itumel
itumel

Reputation: 43

Firebase Realtime Database orderBy() query does not work

I have a Firebase Realtime Database that looks like this

Firebase Database Structure

My browser extension is for creating stories. And each story (under 'userStories') is associated with a particular user (authUID). authID is the id the user is logged in with using Firebase Authentication. Each story receives a key generated by push() when writing to 'stories'.

I am trying to retrieve data using Javascript and sort it in reverse order. I want to display the last story created first.

My JavaScript code (does not work by the way) looks like this:

firebase.database().ref('/userStories/'+authUID).orderByKey().limitToLast(5).once('value').then(function(snapshot)
{
  sendResponse({type: "result", status: "success", data: snapshot.val(), request: request})
}) 

My question is what's wrong with my query statement?

Nothing is happening in terms of sorting. Whether I try orderByValue(), orderByKey() or orderByChild() makes no difference.

Why are the results not being sorted.

Edit:

If my modify my code to the following...

      firebase.database().ref('/userStories/'+authUID).orderByKey().limitToLast(5).once('value').then(function(snapshot)
      {
        let results = [];
        snapshot.forEach(function(child) {
          console.log(child.key,child.val)
          results.push({ key: child.key, value: child.val() });
          console.log(results)
         })
        sendResponse({type: "result", status: "success", data: results, request: request})
      }) 

This is the output to the console...

Console.log Output

As you can see the sorting order is still ascending (which is not what I want).

I want the results in descending order.

Thanks for the suggestion.

Edit:

I got some results (not exactly what I was looking for) by adding the line results.reverse() to reverse the array. There's a sort of the last key but the rest are all mixed up.

      {
        let results = [];
        snapshot.forEach(function(child) {
          console.log(child.key,child.val)
          results.push({ key: child.key, value: child.val() });
          results.reverse()
          console.log(results)
         })
        sendResponse({type: "result", status: "success", data: results, request: request})
      }) 

The results on the console are:

Sorted results in Descending order

Edit:

Sorry to make so many edits but this is the last one. I found a solution by using a spread operator [...] to make copy of the array results and then reverse it. I added the line res = [...results].reverse() and I this time the results are sorted in descending order.

firebase.database().ref('/userStories/'+authUID).orderByKey().limitToLast(5).once('value').then(function(snapshot)
      {
        let results = [];
        let res = [];
        snapshot.forEach(function(child) {
          console.log(child.key,child.val)
          results.push({ key: child.key, value: child.val() });
          res = [...results].reverse()
          console.log(res)
         })

        sendResponse({type: "result", status: "success", data: res, request: request})
      }) 

Here are the results: Sorted Results

Upvotes: 1

Views: 1410

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 600110

Keys in JSON are unordered. So while snapshot has the information about the order of the results, that information is lost as soon as you call snapshot.val().

If you want to maintain the information about order, you'll want to use snapshot.forEach() to loop over the results.

For example, you could convert the results into an array of keys and values:

firebase.database().ref('/userStories/'+authUID).orderByKey().limitToLast(5).once('value').then(function(snapshot)
{
  let results = [];
  snapshot.forEach(function(child) {
    results.push({ key: child.key, value: child.val() });
  });
  sendResponse({type: "result", status: "success", data: results, request: request})
}) 

Upvotes: 4

Related Questions