javascriptfirebasefirebase-realtime-database

Firebase's Realtime Database's `startAt` isn't working as expected


var database = firebase.database(); //db is empty.

function handler(e, prevChildKey) {
    console.log(e.val());
}

database.ref('user').orderByChild('color').startAt('a').on('value', handler);

database.ref('user').set({
    'ryan': {color: "a"},
    'john': {color: "b"},
    'kirsty': {color: "c"},
});

I expect: {ryan: {color: "a"}} to be logged to the console. The reason is because I thought startAt matches keys whose value starts with "a".

Instead, it logs:

{
 john: {color: "b"},
 kirsty: {color: "c"},
 ryan: {color: "a"}
}

Solution

  • A query in Firebase consists of two steps:

    1. You specify what value of each child node to order by, in your case that is the value of color. Firebase reads the nodes, and orders them by that value.
    2. You then specify where to start returning results, which is at child a. Since you don't specify an end condition, Firebase returns all child nodes from the one it starts at.

    If you want to implement a starts with operation, you'll want to combine startAt() with endAt():

    database.ref('user').orderByChild('color').startAt('a').endAt('a\uf8ff').on('value', handler);
    

    The \uf8ff in this example is just a character that is far enough at the end of the character set that the result includes all nodes whose color value starts with a.


    When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.

    Your callback will need to handle this list, by looping using DataSnapshot.forEach to loop over the children:

    function handler(snapshot) {
      snapshot.forEach(function(e) {
        console.log(e.val());
      });
    }
    
    database.ref('user').orderByChild('color').startAt('a').on('value', handler);