Home > OS >  Sort messages in Realtime DB by timestamp
Sort messages in Realtime DB by timestamp

Time:10-06

I am having trouble by getting my messages stored in realtime db in order.

Here's my db structure

messages: {
  $chatId: {
     $messageId: {
       timestamp: 1664884736728,
       sender:"36a72WVw4weQEoXfk3T9gCtOL9n2",
       message: "Hello world"
     }
  }
}

This is my chat repository

  //get all messages of a chat
  Query getMessages(String chatId) {
    //get all messages of a chat
    final messages = _database.ref().child("messages/$chatId");
    //return all messages of a chat
    return messages;
  }
}

and this is how I am displaying it

StreamBuilder(
                stream: _chatRepository.getMessages(chatId).onValue,
                builder: (context, AsyncSnapshot snapshot) {
                  if (snapshot.data != null &&
                      snapshot.data?.snapshot?.value != null &&
                      snapshot.hasData) {
                    final messages = Map.from(snapshot.data?.snapshot.value as Map);
                    return ListView.builder(
                      itemCount: messages.length,
                      scrollDirection: Axis.vertical,
                      itemBuilder: (context, index) {
                        final currChat = messages.values.toList()[index];
                        return BubbleCustom(...),
                        );
                      },
                    );
                  }
                  return Container();
                },
              ),

This is my index in realTimeDB


{
  "rules": {
    "messages": {
      "$chatId": {
        ".indexOn": ["timestamp"]
      }
    }
  }
}

I need to get them in timestamp order. Is there any way I can do this? I hope you can help me. Thanks in advance!

CodePudding user response:

You can use orderByChild to get the messages in the order of a specific child. So there that'd be:

stream: _chatRepository.getMessages(chatId).orderByChild('timestamp').onValue

Don't forget to define an index for timestamp, so that the sorting can be done on the database server.

To learn more on this, see the Firebase documentation on sorting and filtering data.

CodePudding user response:

I solved it by doing it in the frontend like this:

  final messages = Map.from(snapshot.data?.snapshot.value as Map);
                  //sort messages by timestamp ascending order
                  final messagesList = messages.values.toList();
                  messagesList.sort((a, b) => a["timestamp"].compareTo(b["timestamp"]));
                  final newMessagelist = List.from(messagesList.reversed);
   return ListView.builder(
                    physics: const BouncingScrollPhysics(),
                    reverse: true,
                    itemCount: newMessagelist.length,
                    scrollDirection: Axis.vertical,
                    itemBuilder: (context, index) {
                      final currChat = newMessagelist[index];
                      return BubbleCustom(
                        text: currChat["message"],
                        isSender: currChat["sender"] == senderUser.id,
                        tail: true,
                        textStyle: TextStyle(
                          fontSize: 16,
                          color: currChat["sender"] == senderUser.id ? Colors.white : Colors.black,
                        ),
                      );
                    },
                  );

with reverse: true and inverting the list before I render it.

  • Related