3

I'm running into a weird issues in which a Firebase query using orderByChild() doesn't actually order the data. Below is a snapshot of the data that I'm trying to order: (total is off for the sake of this example)

Snapshot of data

This is the code that I've used so far:

Query query = locationComment.orderByKey();
    query.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if (dataSnapshot.getValue() == null) {
                return;
            }
            data.clear();
            adapter.notifyDataSetChanged();
            String userId;
            String time;
            String comment;
            Map<String, String> commentMap = (Map) dataSnapshot.getValue();
            for (Map.Entry<String, String> entry : commentMap.entrySet()) {
                if(!((entry.getKey()).contains("total"))) {
                    String[] keyString = (entry.getKey()).split(",");
                    time = keyString[0];
                    userId = keyString[1];
                    comment = entry.getValue();
                    Date resultdate = new Date(Integer.parseInt(time));
                    data.add(new Comment(comment,
                            DateFormat.getDateTimeInstance().format(resultdate), userId));
                    adapter.notifyItemInserted(data.size());
                }
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

I'm getting each and every key-value pair (barring total) except that it's not in order as expected (ordered by key). The Firebase docs say that the keys are ordered lexicographically if they can't be parsed into a 32 bit integer.

Either way though the order should be as shown in the image but the data that I get back while looping through the map is not in this order.

I would really appreciate it if someone could point me in the right direction. Thanks!

AL.
  • 36,815
  • 10
  • 142
  • 281
Ron7
  • 395
  • 3
  • 7
  • 18
  • What does the data look like that you get back? Could you please update your original post to include this? Thanks – Drew Szurko Feb 24 '17 at 00:23

2 Answers2

9

When you execute a query you get three things:

  • they keys
  • the values
  • the relative order between these

When you convert the result to a Map it can only hold two of these, so the order is lost. To prevent this, you should use the DataSnapshot.getChildren() method:

Query query = locationComment.orderByKey();
query.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        if (dataSnapshot.getValue() == null) {
            return;
        }
        data.clear();
        for (DataSnapshot child : dataSnapshot.getChildren()) {
            ...
        }
        adapter.notifyDataSetChanged();
    }

Also see this example in the Firebase documentation on working with lists: https://firebase.google.com/docs/database/android/lists-of-data#listen_for_value_events

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
1

Looks like your data is badly structured.

Firebase has it's internal way of keying, and Firebase only can order those keys, with additional criteria if wanted. But since your key, is a custom key, firebase can't and won't order this branch.

The solution is to restructure your data in a meaningful way, like this

+ comments
  + total: 13
  + data: 
     + 12uoasjihdou3
        + time: xx
        + userID: xx
        + comment: xx
     + 123tjiueoi134
     + 1piahf9hasheui
     + 6890324890oiuwer

Always use push() to generate new keys, do not create custom keys for lists, thats a total no go

FirebaseDatabase.getReference("comments").child("data").push({yourdata});

if you want to order your data, this is how you do that

FirebaseDatabase.getReference("comments").child("data").orderByChild("time");
xxfast
  • 697
  • 5
  • 14