Display posts in descending posted order

Solution 1:

Since this answer was written, Firebase has added a feature that allows ordering by any child or by value. So there are now four ways to order data: by key, by value, by priority, or by the value of any named child. See this blog post that introduces the new ordering capabilities.

The basic approaches remain the same though:

1. Add a child property with the inverted timestamp and then order on that.

2. Read the children in ascending order and then invert them on the client.

Firebase supports retrieving child nodes of a collection in two ways:

  • by name
  • by priority

What you're getting now is by name, which happens to be chronological. That's no coincidence btw: when you push an item into a collection, the name is generated to ensure the children are ordered in this way. To quote the Firebase documentation for push:

The unique name generated by push() is prefixed with a client-generated timestamp so that the resulting list will be chronologically-sorted.

The Firebase guide on ordered data has this to say on the topic:

How Data is Ordered

By default, children at a Firebase node are sorted lexicographically by name. Using push() can generate child names that naturally sort chronologically, but many applications require their data to be sorted in other ways. Firebase lets developers specify the ordering of items in a list by specifying a custom priority for each item.

The simplest way to get the behavior you want is to also specify an always-decreasing priority when you add the item:

var ref = new Firebase('https://your.firebaseio.com/sell');
var item = ref.push();
item.setWithPriority(yourObject, 0 - Date.now());

Update

You'll also have to retrieve the children differently:

fbl.child('sell').startAt().limitToLast(20).on('child_added', function(fbdata) {
  console.log(fbdata.exportVal());
})

In my test using on('child_added' ensures that the last few children added are returned in reverse chronological order. Using on('value' on the other hand, returns them in the order of their name.

Be sure to read the section "Reading ordered data", which explains the usage of the child_* events to retrieve (ordered) children.

A bin to demonstrate this: http://jsbin.com/nonawe/3/watch?js,console

Solution 2:

Since firebase 2.0.x you can use limitLast() to achieve that:

fbl.child('sell').orderByValue().limitLast(20).on("value", function(fbdataSnapshot) { 
  // fbdataSnapshot is returned in the ascending order
  // you will still need to order these 20 items in
  // in a descending order
}

Here's a link to the announcement: More querying capabilities in Firebase

Solution 3:

To augment Frank's answer, it's also possible to grab the most recent records--even if you haven't bothered to order them using priorities--by simply using endAt().limit(x) like this demo:

var fb = new Firebase(URL);

// listen for all changes and update
fb.endAt().limit(100).on('value', update);

// print the output of our array
function update(snap) {
   var list = [];
    snap.forEach(function(ss) {
       var data = ss.val();
       data['.priority'] = ss.getPriority();
       data['.name'] = ss.name();
       list.unshift(data); 
    });
   // print/process the results...
}

Note that this is quite performant even up to perhaps a thousand records (assuming the payloads are small). For more robust usages, Frank's answer is authoritative and much more scalable.

This brute force can also be optimized to work with bigger data or more records by doing things like monitoring child_added/child_removed/child_moved events in lieu of value, and using a debounce to apply DOM updates in bulk instead of individually.

DOM updates, naturally, are a stinker regardless of the approach, once you get into the hundreds of elements, so the debounce approach (or a React.js solution, which is essentially an uber debounce) is a great tool to have.