0

I have my database as shown below: enter image description here

Note that dev-user-messages is at root level. Now I am trying to query it like this:

get(query(ref(db, path), orderByChild('lastModified'))).then((snapshot) => {
            if (snapshot.exists()) {
                const res = snapshot.val();
                console.log(res);
            }
        });

However no matter which way I order it, I tried using limitToLast and limitToFirst as well but all of them return the response always in the order of keys (i.e. a,b,c,d):

{
    "a": {
        "lastModified": 1
    },
    "b": {
        "lastModified": 2
    },
    "c": {
        "lastModified": 10
    },
    "d": {
        "lastModified": 5
    }
}

Am I doing something wrong here?

Edit:

As suggested by Frank and referring to the following post, I updated my query to be like this:

React.useEffect(() => {
        const path = formMessagesPath(process.env.NODE_ENV === 'production');
        console.log(path);
        get(
            query(ref(db, path), orderByChild('lastModified'), limitToLast(limit))
        ).then((snapshot) => {
            if (snapshot.exists()) {
                console.log(snapshot.forEach((item) => console.log(item.val())));
            }
        });
    }, []);

However changing this line:

get(
            query(ref(db, path), orderByChild('lastModified'), limitToLast(limit))
        )

Output:

enter image description here to

get(
            query(ref(db, path), orderByChild('lastModified'), limitToFirst(limit))
        )

yields the same result: Output: enter image description here

I understand invoking .val() resets the order but what is the problem now when I use forEach?

Edit 2: Okay, now I think I fully understand this, so my question is majorly how can I change the order of sorting. (Currently it seems to be ascending, how to make it descending?):

Desired outcome:

Data:

{
    "a": {
        "lastModified": 1
    },
    "b": {
        "lastModified": 2
    },
    "c": {
        "lastModified": 10
    },
    "d": {
        "lastModified": 5
    }
}

I would want two cases:

1.fetch last N child (ordered By lastModified key in descending order): [10,5,2] 2. Fetch last N child (ordered By lastModified key in ascending order): [2,5,10]

My understanding is orderBy('lastModified') orders data as: [1,2,5,10] and limitToLast(100) would return the data as: [1,2,5,10] However, when I do limitToFirst(100), the data remains the same: [1,2,5,10]

Now what if I want it to be ordered in descending way first and then apply limitToFirst or limitToLast based upon my requirement?

Shivam Sahil
  • 4,055
  • 3
  • 31
  • 62
  • 1
    The snapshot you get contains three things: the nodes that match your query, the keys of those nodes, the order of these nodes. But when you call `.val()` on the snapshot, the object you get back only has space for the keys and the values, so the info on node order is lost. To solve this, use `snapshot.forEach()` to process the results in order, and then call `.val()` on each child node in the loop. – Frank van Puffelen Jan 21 '23 at 17:48
  • Hi @FrankvanPuffelen can you please check my edit. I got your point but despite doing it, I am getting the same order! – Shivam Sahil Jan 22 '23 at 04:52
  • Those last two code snippets and their output look the same to me at first glance. Can you highlight what the difference is, or (probably better) just show what doesn't work. – Frank van Puffelen Jan 22 '23 at 04:54
  • Hi @FrankvanPuffelen, you're right. I didn't analyse it correctly. So sorry for the confusion. I think my actual question was the ability to sort the first list in switched order. (i.e. ordering it based on requirement: Either ascending or descending). I have added edit to the question – Shivam Sahil Jan 22 '23 at 05:07
  • 1
    Firebase Realtime Database always sorts in ascending order. If you want descending, you'll either have to reverse in your application code, or store in inverted value (i.e. -10, -5, -2, -1). Also see [this](https://stackoverflow.com/questions/60213660/) and [here](https://stackoverflow.com/questions/70551039/getting-highest-score-values-from-firebase-database). – Frank van Puffelen Jan 22 '23 at 06:08
  • I liked that second approach of yours! That's super creative. Thanks a lot @FrankvanPuffelen I think that's all I had – Shivam Sahil Jan 22 '23 at 06:12

1 Answers1

0

As suggested by Frank, The issue here is that when extracting values using .val() method, the keys order change, however using something like:

const results = [];
snapshot.forEach((item) => results.push(item.val()));

would work. Currently there's no way to support sort ordering in firebase, but an innovative way could be to keep your timestamps multiplied by -1 and rest will automatically be taken care of.

However this comes with a limitation that you have to decide which ordering you want for your data and that there's no way to reverse the order at firebase side, rather you can perform the same on your frontend app or the backend app.

I am not sure why this question was re-opened again but this is all that I have concluded for my answer. I am closing this question with this answer for now.

Shivam Sahil
  • 4,055
  • 3
  • 31
  • 62