3

When I get all the data from the database without any query, I get the last entries from the database (keys are generated to work this way). Something like this:

var ref = firebase.database().ref('myObj').limitToFirst(100);
ref.on("value", function(snap){
    console.log(snap.val());
});

This way I get all the objects I need ordered properly. But if I add a query to filter some data, I lost the order from the original.

var ref = firebase.database().ref('myObj').orderByChild('myChild').equalTo('myproperty').limitToFirst(100);
ref.on("value", function(snap){
    console.log(snap.val());
});

This way I am not receiving the most recent data as I get when I don't apply any filter.

How can I solve that?

Peter Haddad
  • 78,874
  • 25
  • 140
  • 134
cor
  • 3,323
  • 25
  • 46
  • Can't you fetch the data first, and then apply the filters? – Vinod Bhavnani Dec 12 '17 at 07:15
  • It is a huge amount of data, I prefer doing it server side – cor Dec 12 '17 at 07:36
  • It sounds like you're trying to order/filter on two properties, which is not possible with the Firebase Realtime Database. See http://stackoverflow.com/questions/26700924/query-based-on-multiple-where-clauses-in-firebase – Frank van Puffelen Dec 15 '17 at 03:48
  • 1
    @FrankvanPuffelen as far as I know I'm trying to filter for a single property.. I don't understand why are you saying that – cor Dec 15 '17 at 10:36
  • 1
    The first snippet you show has an implicit `orderByPriority()/orderByKey()` operation. In your second snippet, you explicitly order/filter by `myChild` and then seem to be expecting it to order the results by key. That requires two ordering operations, which can't be done on the server. – Frank van Puffelen Dec 15 '17 at 15:23
  • But if I'm not wrong "equalTo" operator needs the previews orderByChild operation in order to know which attribute am I ordering. So its the same as saying that filtered data losts the default order? Because I only want to filter for one attribute and get the data at the default order. – cor Dec 15 '17 at 15:27

1 Answers1

2

I just realised what happens with this:

.ref('myObj').orderByChild('myChild').limitToFirst(100);

is that orderByChild('myChild') reads JSON in descending order (from the bottom) and then that list is queried again by limitToFirst(100) in ascending order ("queried again" - I mean maybe in a more efficient way than literally querying list again). So what was originally at the bottom, goes to the top - you get your 100 records starting from the bottom of your Firebase JSON file.

You can try it out (tested with AngularFire2 - remove orderByChild('size') to see the change in ordering).

Some ways to revert the order:

First way as you wrote, is simply change query to LimitToLast()

Other ways:

Revert pipe:

<div *ngFor="let item of listObservable | async | reverse">

Using AngularFre2, you could take advantige of Rxjs features:

this.stories = af.database.list('/myObj', {
  query: {
    limitToLast: 100
  }
}).map((array) => array.reverse()) as FirebaseListObservable<any[]>;

Or one, interesting, way to reverse via CSS:

#container{
  display: -webkit-flex;
        display: -moz-flex;
        display: -ms-flex;
        display: -o-flex;  
        -webkit-flex-direction: column-reverse;
        -moz-flex-direction: column-reverse;
        -ms-flex-direction: column-reverse;
        -o-flex-direction: column-reverse;
}
Julius Dzidzevičius
  • 10,775
  • 11
  • 36
  • 81
  • 1
    it just works for me changing `limitToFirst` by `limitToLast` i don't need to do anything more. Thanks for pointing me to the correct direction! – cor Dec 19 '17 at 07:50
  • @cor - I just realised what was the cause of this - you can read update answer. Please comment if you find something not right – Julius Dzidzevičius Dec 19 '17 at 09:01