10

I am learning about Firebase Firestore through official documentation. I was trying following code. Notifications are added using add() method of firestore.

FirebaseFirestore.getInstance().colRefNotifications()
            .orderBy("timestamp", Query.Direction.DESCENDING)
            .get()
            .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
        @Override
        public void onSuccess(QuerySnapshot documentSnapshots) {

            if (!documentSnapshots.isEmpty()){

                listNotifications.clear();
                recyclerViewNotification.removeAllViews();

                for (DocumentSnapshot data : documentSnapshots){

                    Notification notification = data.toObject(Notification.class);
                    listNotifications.add(notification);
                }

                notificationGeneralAdapter.notifyDataSetChanged();
            }
        }
    });

Notification.java

private String text;
private String key;
private Date timestamp;

public Notification() {
}

public Notification(String text, String key, Date timestamp) {
    this.text = text;
    this.key = key;
    this.timestamp = timestamp;
}

public String getText() {
    return text;
}

public String getKey() {
    return key;
}

public Date getTimestamp() {
    return timestamp;
}

Firestore

firestore_snapshot

I am ordering notifications by timestamp in descending direction. But, as you can see in the following snapshot, it is not showing desired output.

Snapshot

What am I doing wrong? Thank you for your help.

Pratik ED
  • 151
  • 1
  • 1
  • 13
  • 1
    if you show Notification class and model in fs i mb help you – abbath0767 Feb 05 '18 at 14:52
  • The question has edited. Please check. – Pratik ED Feb 05 '18 at 15:31
  • hm...strange. In my case work correctly. I think problem out of this code. Please, add after create each creating object Notification Log (mb debug mode in as) and see what added. And you enable indexing? – abbath0767 Feb 05 '18 at 16:30
  • Strange thing I noticed is, the code works correctly if I restart the app, but not always. Yes, I have enabled the indexing. To add an index, we require min. two fields. In my case, there is only one field ("timestamp"). – Pratik ED Feb 05 '18 at 17:36

2 Answers2

5

This is happening because of nested queries. If you put a query inside a listener (success/failure/complete), orderBy method will not work. Place your next query inside onBindViewHolder of the RecyclerView adapter.

FirebaseFirestore.getInstance().colRefNotifications()
        .orderBy("timestamp", Query.Direction.DESCENDING)
        .get()
        .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
    @Override
    public void onSuccess(QuerySnapshot documentSnapshots) {

        if (!documentSnapshots.isEmpty()){
           ....

           /**If you are nesting queries like this, move second query to**/
           /**onBindViewHolder of the RecyclerView adapter**/

           FirebaseFirestore.getInstance().colRefUsers()
           .get()
           .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
           @Override
           public void onSuccess(QuerySnapshot documentSnapshots) {

               if (!documentSnapshots.isEmpty()){
               ....

               }
             }
          });
        }
    }
});
pratiked
  • 1,712
  • 1
  • 11
  • 18
1

This is happening because you are not using the timestamp as server value timestamp. You are setting the timestamp using the Date class this is not how you must do it.

Here is how you can add the timestamp using a model class. So, change your model class according with my answer from that post, also don't forget the @ServerTimestamp annotation and then your query will work fine.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Annotation nothing to do with it – abbath0767 Feb 05 '18 at 16:30
  • @abbath0767 Yes it does. Firebase servers will read your timestamp field as it is a `ServerTimestamp`. – Alex Mamo Feb 05 '18 at 16:33
  • 1
    it's need only for sync time in difference locales. but if you don't need this feature you don't need to know about ServerTimestamp or FieldValue. PS: I do not deny the need for the use of this feature, but sorting nothing to do with it – abbath0767 Feb 05 '18 at 16:53
  • @abbath0767 And it also won't help you correctly query, as you can see also in this case. – Alex Mamo Feb 05 '18 at 16:56
  • In my opinion, this is happening because of cached data or may be something to do with Indexes. To add an index, we require min. two fields. In my case, there is only one field ("timestamp"). – Pratik ED Feb 05 '18 at 17:32
  • There has nothing to do with indexes because all document fields are automatically indexed. You using a query based on a single field, so there is no problem with that. Have you tried my solution? – Alex Mamo Feb 05 '18 at 17:35
  • @AlexMamo: I will test your suggestion. But what if I want to order the query by different field? It can be string or int or anything. – Pratik ED Feb 05 '18 at 17:43
  • You can order by any field you have as a property in your model class. Ok, try my solution and keep me posted. – Alex Mamo Feb 05 '18 at 17:45
  • But isn't only the annotation, check that answer again. Remove the date from your constructor! The must be left empty. Remove the old data, add fresh data and try again. Does it work now? – Alex Mamo Feb 05 '18 at 18:00
  • small comment - when you add data in constructor (bewfore push to firestore) use FieldValue.serverTimestamp() - then time should create correctly – abbath0767 Feb 05 '18 at 20:41
  • @abbath0767 OP is using a model class. There is no need to use that. Letting the date uninitialized is enough to solve the problem. – Alex Mamo Feb 06 '18 at 08:25