Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

orderByChild not working in Firebase

I am trying to query my database such that it retrieves an ordered list based on a child key. I do it as follows (see below), but nothing happens, meaning that it returns an object ordered exactly in the same way as it is stored in the Firebase database. What is going on?

self.getAllProfiles = function () {
    var qProfile = $q.defer();
    var ref = new Firebase(FBURL);
    ref.child("users").orderByChild('last_update').on("value", function (snapshot) {
        console.log(snapshot.val()) // HERE IS WHERE IT SHOULD BE ORDERED
        qProfile.resolve(snapshot.val());
    }, function (errorObject) {
        qProfile.reject(errorObject);
    });
    return qProfile.promise;
};

To add, my users node looks as follows:

users
   /$username
       /last_update
       /id
       /data
          /profile_image
          /display_name

Here is a snapshot:

Tester: Object
   github: Object
   last_update: 1447732462170
   userId: "github:12345"
like image 634
JohnAndrews Avatar asked Nov 24 '15 12:11

JohnAndrews


2 Answers

When you call snapshot.val(), you are getting back a JSON object. The order of keys in a JSON object is determined by your browser and not by Firebase.

To get the children in order use the built-in forEach method of the snapshot:

self.getAllProfiles = function () {
    var qProfile = $q.defer();
    var ref = new Firebase(FBURL);
    ref.child("users").orderByChild('last_update').on("value", function (snapshot) {
        snapshot.forEach(function(child) {
            console.log(child.val()) // NOW THE CHILDREN PRINT IN ORDER
        });
        qProfile.resolve(snapshot.val());
    }, function (errorObject) {
        qProfile.reject(errorObject);
    });
    return qProfile.promise;
};

You can leave the q.resolve() call where it is: snapshot.forEach() is not an asynchronous call.

like image 115
Frank van Puffelen Avatar answered Oct 12 '22 07:10

Frank van Puffelen


I know this question has been answered and is more than 1 year old, but since there are still some confusion in the comment section, I would like to add some information.

The problem

The original problem is that the OP want to retrieve an ordered list based on a child key from Firebase realtime database, but the .orderByChild('arg') does not work as expected.

But what didn't work as expected is not .orderByChild('arg'), but .on("value", callback). Because .on("value", callback) works a bit of different from other eventTypes like .on("child_added", callback).

Example

Say we have a firebase realtime database as below:

{
    myData: {
        -KYNMmYHrzLcL-OVGiTU: {
             NO: 1,
             image: ...
        },
        -KYNMwNIz4ObdKJ7AGAL: {
             NO: 2,
             image: ...
        },
        -KYNNEDkLpuwqQHSEGhw: {
             NO: 3,
             image: ...
        },
    }
}

--

If we use .on("value", callback), the callback() will be called 1 time, and return an Object Array of 3 objects.

ref.on("value", function(snapshot) {
    console.log(snapshot.val());
    // Please see Frank van Puffelen's answer
}

enter image description here

--

If we use .on("child_added", callback), the callback() will be called 3 times, each time returns an Object, and they are returned in order.

ref.once("child_added", function(snapshot) { 
    console.log(snapshot.val());
    // The objects are returned in order, do whatever you like
}

enter image description here

Conclusion

If you only need to fetch ordered data from firebase (e.g. to initialize UI.) Then ref.orderByChild('arg').once("child_added", callback) suits you well, it is simple and easy to use.

However, if for some reason you need to use ref.orderByChild('arg').on("value", callback), then please see Frank van Puffelen's answer.

Reference

Please read Firebase Document for more information about on(eventType, callback, cancelCallbackOrContext, context), their arguments and their return values.

Another useful document: Work with Lists of Data on the Web

like image 19
user2875289 Avatar answered Oct 12 '22 07:10

user2875289