Reputation: 6501
I am trying to get the last message of every single conversation between User 1 and User N.
I've managed to compile the below together, however it is throwing the above, aforementioned error. How can I solve this, with ObjectIds, as that is what I have in the DB, not strings?
await MostRecentMessages.aggregate(
[
{
$match: {
$or: [
{ from: mongoose.Types.ObjectId(id) },
{ to: mongoose.Types.ObjectId(id) }
],
deletedBy: { $ne: id }
}
},
{ $sort: { date: -1 } },
{ $project: { _id: 1, from: 1, to: 1, conversation: 1, date: 1 } },
{
$group: {
_id: {
lastMessage: {
$cond: [
{
$gt: [
{ $substr: ["$to", 0, 1] },
{ $substr: ["$from", 0, 1] }
]
},
{ $concat: ["$to", " and ", "$from"] },
{ $concat: ["$from", " and ", "$to"] }
]
}
},
conversation: { $first: "$$ROOT" }
}
},
{
$lookup: {
from: "conversations",
localField: "conversation",
foreignField: "_id",
as: "conversation"
}
},
{ $unwind: { path: "$conversation" } },
{
$lookup: {
from: "users",
localField: "to",
foreignField: "_id",
as: "to"
}
},
{ $unwind: { path: "$to" } },
{
$lookup: {
from: "users",
localField: "from",
foreignField: "_id",
as: "from"
}
},
{ $unwind: { path: "$from" } }
],
function(err, docs) {
if (err) {
console.log(err);
} else {
console.log("MostRecentMessages", docs);
return res.json(docs);
}
}
);
My schema, if it matters:
const MostRecentMessageSchema = new Schema({
to: {
type: mongoose.Schema.Types.ObjectId,
ref: "user"
},
from: {
type: mongoose.Schema.Types.ObjectId,
ref: "user"
},
conversation: {
type: mongoose.Schema.Types.ObjectId,
ref: "conversation"
},
deletedBy: {
type: [String]
},
date: {
type: Date,
default: Date.now
}
});
Here are the 5 relevant documents:
// db.MostRecentMessages
_id:5dca7a61e95bd3341cad64b9
to:5dca58c21825d8269a32cb10
from:5dca58ce1825d8269a32cb11
conversation:5dca7aea51b626350fa865dd
date:2019-11-12T09:24:49.906+00:00
_id:5dca7ab0d3a44a34c98b7263
to:5dca58ce1825d8269a32cb11
from:5dca58c21825d8269a32cb10
conversation:5dca7ab0d3a44a34c98b7262
date:2019-11-12T09:26:08.125+00:00
// db.Conversation
_id:5dca7a61e95bd3341cad64b8
text:"Test1"
user:5dca58ce1825d8269a32cb11 // sender
recipient:5dca58c21825d8269a32cb10
createdAt:2019-11-12T09:24:49.827+00:00
_id:5dca7ab0d3a44a34c98b7262
text:"Test2"
user:5dca58c21825d8269a32cb10 // sender
recipient:5dca58ce1825d8269a32cb11
createdAt:2019-11-12T09:26:08.105+00:00
_id:5dca7aea51b626350fa865dd
text:"Test3"
user:5dca58ce1825d8269a32cb11 // sender
recipient:5dca58c21825d8269a32cb10
createdAt:2019-11-12T09:27:06.562+00:00
I copied and pasted the answer below, but it only returns the message with text Test2
Upvotes: 0
Views: 942
Reputation: 4363
Link in comment is for your own knowledge... Now let's see what is working (it will probably sounds like 'deja vu' for you, but it works!). All (and your aforementioned error) take place in $group stage
db.lastMessage.aggregate([
{
$match: {
$or: [
{
from: ObjectId("5a934e000102030405000001")
},
{
to: ObjectId("5a934e000102030405000001")
}
],
deletedBy: {
$ne: ObjectId("5a934e000102030405000001")
}
}
},
{
$sort: {
date: -1
}
},
{
$project: {
_id: 1,
from: 1,
to: 1,
conversation: 1,
date: 1
}
},
{
$group: {
_id: {
userConcerned: {
$cond: {
if: {
$eq: [
"$to",
ObjectId("5a934e000102030405000001")
]
},
then: "$to",
else: "$from"
}
},
interlocutor: {
$cond: {
if: {
$eq: [
"$to",
ObjectId("5a934e000102030405000001")
]
},
then: "$from",
else: "$to"
}
}
},
from: {
$first: "$from"
},
to: {
$first: "$to"
},
date: {
$first: "$date"
},
conversation: {
$first: "$conversation"
}
}
},
{
$lookup: {
from: "conversations",
localField: "conversation",
foreignField: "_id",
as: "conversation"
}
},
{
$unwind: {
path: "$conversation"
}
},
{
$lookup: {
from: "users",
localField: "to",
foreignField: "_id",
as: "to"
}
},
{
$unwind: {
path: "$to"
}
},
{
$lookup: {
from: "users",
localField: "from",
foreignField: "_id",
as: "from"
}
},
{
$unwind: {
path: "$from"
}
}
])
You can verify here . I just modified your group stage with the one i already provided in your other question.
Upvotes: 1