0

I am working on a chat application. I want to get the last 20 messages from the Firebase database and in order, the message was added. For example, if I have sent 3 different message "Hi", "What's up", "Bye". I should get "Hi", "What's up", "Bye" in the same order.

The query I am using is following.

ref.child(Constants.messageListKey).child("-Laray524a9Na-C7zdij").queryLimited(toLast: Constants.messageLimitPerCall).observeSingleEvent(of: .value, with: { (snapshot) in 
       let currentUserChatList = snapshot.value as? NSDictionary
       if let chatList = currentUserChatList?.allKeys { 
         // parsing the data here
       }
}

I even tried using .queryOrderedByKey() and .queryOrdered(byChild:) but still the same result.

The result that I am getting is not in order. For example, I am getting "What's up", "Hi", "Bye". The result is not even ascending order nor descending order. It is just a random order.

The scheme which I am using is like this:

-chatList
    -autogeneratedKey
         -msg = "Some Message"

Is there anything that I am missing? If there is any details that I have missed please let me know to understand my question better.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Zohaib Brohi
  • 576
  • 1
  • 7
  • 15
  • Firebase Database queries always return results in ascending order. If you need them in descending order, you'll either have to reverse them client-side, or store an inverted value in the database. See https://stackoverflow.com/q/45137899 – Frank van Puffelen Sep 28 '19 at 20:31

1 Answers1

2

I would suggest adding a time stamp to you nodes which will guarantee the order. You would then also add a negative time stamp as well which would enable descending sort

messages
   msg_0
     msg: "What's up"
     timestamp: 20190927013000
     neg_timestamp: -20190927013000
   msg_1
     msg: "Hi"
     timestamp: 20190927020000
     neg_timestamp: -20190927020000

Then you can query but timestampt for ascending and neg_timesstamp for descending and will be guarateeed order.

The nodes are in random order because you're reading them as a Dictionary which are unordered sets of key: value pairs.

let currentUserChatList = snapshot.value as? NSDictionary

If you want them IN order then do this

let currentUserChatList = snapshot.children.allObjects as! [DataSnapshot]

which will maintain their order, and you can iterate over them with a for loop as in your question. Each child will be a DataSnapshot as well so you can access the child nodes with

let child in currentUserChatList {
   let msg = child.childSnapshot(forPath: "msg").value as? String ?? "No Msg"
}
Jay
  • 34,438
  • 18
  • 52
  • 81
  • For testing purpose, I create a new node and adding timestamp. And used .queryOrdered(byChild: "timestamp"). But this does not work for me either. – Zohaib Brohi Sep 28 '19 at 18:07
  • @MrBrohi Two things. 1) Include the updated code in your question and 2) remember you are querying by .value so all of the nodes are returned within the snapshot. Show your code how you are accessing the child data within the snapshot – Jay Sep 28 '19 at 18:14
  • Thank you very much. that was the problem. did not think of that. – Zohaib Brohi Sep 28 '19 at 19:40