Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correctly sort nodes from newest to oldest

I am using a FirebaseRecyclerAdapter to inflate a RecyclerView with data provided by the Firebase Realtime Database.

I began sorting the nodes by their child date which was set to be the value of ServerValue.TIMESTAMP. I added a indexOn property to the parent node of the nodes I want to sort with the value date to the Firebase Database Rules.

"parent-node": {
  ".read": "auth != null",
  ".write": "auth != null",
  ".indexOn" : "date",
  ...
}, 

This worked fine but newer nodes were added to the end of my RecyclerView. As the FirebaseRecyclerAdapter and its FirebaseArray add nodes with a ChildEventListener, it means that the data was sorted from oldest to newest.

I managed to reverse this by using the negative value of ServerValue.TIMESTAMP.

private void prepareUpload() {
    //mDatabase is a reference to the root of the Firebase Database
    final DatabaseReference timestampReference = mDatabase.child("timestamp");
    final String timestampKey = timestampReference.push().getKey();
    timestampReference.child(timestampKey).setValue(ServerValue.TIMESTAMP);
    timestampReference.child(timestampKey).addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if (dataSnapshot.getValue() != null) {
                if (!(Long.parseLong(dataSnapshot.getValue().toString()) < 0)) {
                    timestampReference.child(timestampKey).setValue(0 - Long.parseLong(dataSnapshot.getValue().toString()));
                } else {
                    upload(/*Starting upload with new timestamp here (this is just a dummy method)*/);
                    timestampReference.child(timestampKey).removeValue();
                }
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.e(TAG, databaseError.getMessage());
        }
    });
}

Now the nodes I want to sort look like this.

{
  "-K_tlLWVO21NXUjUn6ko" : {
    "date" : -1483806697481,
    "debug" : "old",
    ...
  },
  "-K_tmjVqTUcKXHaQDphk" : {
    "date" : -1483807061979,
    "debug" : "newer",
    ...
  },
  "-K_uC-AJIvDOuBzhJ3JJ" : {
    "date" : -1483813945897,
    "debug" : "newest",
    ...
  }
}

They are sorted from newest to oldest and get added to the top of my RecyclerView exactly as I wanted it to be.

Coming to my personal question:

  • Is this a proper way to sort nodes from newest to oldest? This seems like a big workaround to me.
  • Am I missing something?

Thanks in advance!

Edit: I just saw that my prepareUpload() method is uselessly sending the negative value to the database again, just to receive it once again afterwards.. I will change this to calculate the negative value on client side. Please ignore this.

like image 834
Rodrigo Ehlers Avatar asked Jan 11 '17 15:01

Rodrigo Ehlers


2 Answers

No, you are not missing anything. And yes, that's a proper way to sort nodes from newest to oldest.

That's just the way firebase works. Many times, you might feel like you're doing a big workaround and you think "There must be a simpler way to do this", but there's probably not.

Firebase is indeed a great platform to build your application on. But it still has a few things to improve, like the realtime database. I mean, there is no way to query your data properly. You may be able to do some basic filtering and sorting, but If you want to do more than that, you're on your own.

To help us with that, they have created the Firebase Database for SQL Developers Series which you can watch on this link. Those series explain that there is no proper/default way to structure your data on Firebase. Everytime you start a different project, you'll always have to spend some minutes brainstorming about how you can structure the data in a way that it simplifies and reduces queries for better performance.

I hope Google some day implements more searching and filtering capabilities in this data service.

like image 153
Rosário Pereira Fernandes Avatar answered Oct 09 '22 16:10

Rosário Pereira Fernandes


What you have done is absolutely correct. The only difference is, you should have both, a timestamp and a negativeTimestamp key just in case you need either of them. It all depends on your requirements anyways.

In-fact people from firebase suggest the same. You can watch this youtube video and move to 04:40 to see the answer to your question from the firebase team themselves.

like image 37
Srujan Barai Avatar answered Oct 09 '22 16:10

Srujan Barai