I'm making a chat app, and there will be only one conversation between two person so I didn't make conversation table or ID and the way I want to show list of chats to clients will be like this:
I will get the latest message related to each conversation, conversations are filtered by sender/receiver ID's,
So if there is 2 message in database and the first one has this data :
{
sender: "User.x.ID",
receiver: "User.y.ID",
msg: "How are you?",
},
{
sender: "User.y.ID",
receiver: "User.x.ID",
msg: "Good thanks, and you?",
},
The latest message will be "Good thanks, and you?"
This my messageSchema
:
{
sender: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
receiver: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
usersRelated: {
type: Array,
},
msg: {
type: String,
}
}
This is my code:
const Chats = await Message.aggregate([
{ $sort: { createdAt: -1 } },
{
$match: {
$expr: {
usersRelated: [req.user.id],
},
},
},
{
$group: {
_id: {
sender: "$sender",
receiver: "$receiver",
},
messages: {
$top: {
sortBy: { createdAt: -1 },
output: "$$ROOT",
},
},
},
},
{ $replaceWith: "$messages" },
])
And it returns both of the messages which I don't want, I only want the latest message which will be : "Good thanks, and you?"
.
The reason behind of my need is :
I am trying to show the lists of chats with the preview of latest message same as most of chat apps.
So if you are logged in as User X
what you will see in your list of chat will be one chat with User Y
and they responded to you: "Good thanks, and you?"
and if you click on the chat, then I will load all of the messages related to this two user which will be like this :
User X said : How are you?
User Y Said : Good thanks, and you?
Maybe this one:
db.collection.aggregate([
{
$group: {
_id: { $sortArray: { input: ["$sender", "$receiver"], sortBy: 1 } },
messages: {
$top: {
sortBy: { createdAt: -1 },
output: "$$ROOT"
}
}
}
},
{ $replaceWith: "$messages" },
])
$top
was introduced in MongoDB version 5.2. If you run an older version, then try this:
db.collection.aggregate([
{ $sort: { createdAt: -1 } },
{
$group: {
_id: { $sortArray: { input: ["$sender", "$receiver"], sortBy: 1 } },
messages: { $first: "$$ROOT" }
}
},
{ $replaceWith: "$messages" },
])