Reputation: 134
Let's say I have the following documents in a collection (messages
):
[
{
_id: 1,
message: "...",
participants: [1, 2],
datetime_created: ...
},
{
_id: 2,
message: "...",
participants: [4, 9],
datetime_created: ...
},
{
_id: 3,
message: "...",
participants: [2, 1],
datetime_created: ...
},
{
_id: 4,
message: "...",
participants: [3, 6],
datetime_created: ...
}
]
Now I'm trying to get the last conversation message between participants 1 (currently logged in user) and 2. I tried writing aggregation pipeline like this:
[
{
$match: {
participants: {
$in: [1] // logged in user
}
}
},
{
$sort: {
datetime_created: -1
}
},
{
$group: {
_id: "$participants",
last_message: {
$first: "$$ROOT"
}
}
}
]
It works but not completely. The problem is $group
groups participants
in such way that [1, 2]
and [2, 1]
are considered different elements because an array is an ordered collection of data. Is there a MongoDB-only way to disregard order in an array?
One solution would be to sort participants
during the data insertion which would work but I'd rather have a solution which works on the database side only.
Upvotes: 1
Views: 36
Reputation: 46491
You can use below aggregation
[
{ "$match": { "participants": { "$in": [1] }}},
{ "$unwind": "$participants" }
{ "$sort": { "participants": 1 }},
{ "$group": {
"_id": "$_id",
"participants": { "$push": "$participants" },
"message": { "$first": "$message" },
"datetime_created": { "$first": "$datetime_created" },
}},
{ "$sort": { "datetime_created": -1 }},
{ "$group": {
"_id": "$participants",
"last_message": { "$first": "$$ROOT" }
}}
]
Upvotes: 1