Boomerange
Boomerange

Reputation: 665

How to get messages ordered by timestamp

i want to get all messages by their creation date (which is timestamp).

My data structure looks like this:

messages
  XRJONcahNUgeNrfkH3cmITJt3409 (auto uid of owner - user)
    -KoOSxA2Iajk3kv20U_p (automatic uid generated by Firebase)
      message: "Hi"
      senderId: "X8Oxg5J9Imb12C1iYBXJT9P48909"
      senderName: "Dave"
      timestamp: 1505813320526 (automatic timestamp)
    -GdOSxR2Iajk3kv20U_p --- I NEED TO SORT THESE UIDS
      message: "Hello"
      senderId: "G7Oxg5J9Imb12C1iYBXJT9P48909"
      senderName: "Frank"
      timestamp: 1505813321024 (automatic timestamp)

And I get all messages like this:

database.child("messages").child(ownersId).observeSingleEvent(of: .value, with: { (snapshot) in
            print(snapshot)
            if let messagesDict = snapshot.value as? [String:AnyObject] {
                for (_,message) in messagesDict {
                    self.messages.append((message["message"] as? String)!)
                    self.users.append((message["senderName"] as? String)!)
                    self.timestamps.append((message["timestamp"] as? IntMax)!)
                }
            }
            completionHandler(true)

        }) { (error) in
            print(error.localizedDescription)
            completionHandler(false)
        }

So the question is, how can I get all messages ordered from the oldest to the newest? I dont know how can I use ordering methods (queryOrderedByKey(), queryOrderedByValue() or queryOrdered(byChild: "timestamp") in this specific case. Firebase sends me data in random order (I dont know if it is random, but it is not sorted by date).

Upvotes: 1

Views: 2392

Answers (2)

Rashwan L
Rashwan L

Reputation: 38833

You use database.queryOrdered instead of database.child like this:

database.queryOrdered(byChild: "messages"). observeSingleEvent(.value, with: { (snapshot) in
    print("\(snapshot.value)")
}

But you could also get the data as you have done today and then sort the list self.timestamps instead:

self.timestamps.sorted(by: { $0 > $1 })

Update:
Create a model and append your properties to that model and then append to a list and sort that list after that. Like this:

struct Model {
    let message: String?
    let senderId: String?
    let senderName: String?
    let timestamp: IntMax

    init(message: String?, senderId: String?, senderName: String?, timestamp: IntMax?) {
        self.message = message
        self.senderId = senderId
        self.senderName = senderName
        self.timestamp = timestamp
    }
}

var models = [Model]()
models.sorted(by: { $0.0.timestamp > $0.1.timestamp })

Update 2:
To add the models checkout the code example below:

database.child("messages").child(ownersId).observeSingleEvent(of: .value, with: { (snapshot) in
    print(snapshot)
    var models = [Model]()
    if let messagesDict = snapshot.value as? [String:AnyObject] {
        for (_,message) in messagesDict {
            if let message = message["message"] as? String, let senderName = message["senderName"] as? String, let timestamp = message["timestamp"] as? IntMax, let senderId = message["senderId"] as? String {
                let model = Model(message: message, senderId: senderId, senderName: senderName, timestamp: timestamp)
                models.append(model)
            }
        }
        models.sorted(by: { $0.0.timestamp > $0.1.timestamp })
    }
    completionHandler(true)

}) { (error) in
    print(error.localizedDescription)
    completionHandler(false)
}

Upvotes: 2

Frank van Puffelen
Frank van Puffelen

Reputation: 598797

As Rashwan said, you'll need to call queryOrderedByChild() to get the items returns in the correct order. Then you loop over snapshot.children to ensure you also process them in the correct order.

So:

database.child("messages").queryOrdered(byChild: "timestamp").observe(.value, with: { snapshot in
    for child in snapshot.children.allObjects as! [DataSnapshot] {
        print("\(child.key)")
    }

    completionHandler(true)
})

The important thing inside the callback is to not convert the entire snapshot into a dictionary, because the dictionary won't maintain the order of the items.

Upvotes: 3

Related Questions