У меня есть модель MostRecentMessage
, определенная как
const MostRecentMessage = 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"
},
date: {
type: Date,
default: Date.now
}
});
Всякий раз, когда пользователь A отправляет сообщение пользователю B, документ создается, если его не существует. Каждый раз, когда пользователь A отправляет сообщение пользователю B, этот документ обновляется новыми conversation
и date
. Примером документа является:
_id: ObjectId(5dc46521cf670a0017d2434d)
to: ObjectId(5dc464ce2fd75700178c1ad4) // User B
from: ObjectId(5dc464fc2fd75700178c1ad5) // User A
conversation: ObjectId(5dc465c6cf670a0017d24363)
date: 2019-11-07T18:40:33.242+00:00
__v: 0
Идея состоит в том, что это поможет отследить все последние сообщения определенным пользователям.
Аналогично, пользователь B может отправить пользователю A сообщение. Будет создан новый документ, аналогичный приведенному выше,
_id: ObjectId(5dc46521cf670a0017d2434d)
to: ObjectId(5dc464fc2fd75700178c1ad5) // User A
from: ObjectId(5dc464ce2fd75700178c1ad4) // User B
conversation: ObjectId(5dc465c6cf670a0017d24363)
date: 2019-11-07T18:40:33.242+00:00
__v: 0
И этот документ будет обновляться при каждом новом сообщении, которое пользователь B отправляет пользователю A.
Теперь ниже мойзапрос агрегации .. но проблема в том, что он возвращает только один разговор. Может быть 10 пользователей, разговаривающих с пользователем A, но он все равно вернет только один документ.
const { id } = req.user;
try {
await MostRecentMessages.aggregate(
[
{
$match: {
$or: [
{ from: mongoose.Types.ObjectId(id) },
{ to: mongoose.Types.ObjectId(id) }
]
}
},
{ $project: { _id: 1, from: 1, to: 1, conversation: 1, date: 1 } },
{ $sort: { date: -1 } },
{
$group: {
_id: null,
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" } }
],
function(err, docs) {
if (err) {
console.log(err);
} else {
return res.json(docs);
}
}
);
} catch (err) {
console.log(err);
return res.status(500).send("Server error");
}
Что я здесь не так делаю?
Редактировать: что у меня сейчас:
С этим кодом, если
User A messages User B, 'Test1'
User B messages User A, 'Test2'
User A messages User B, 'Test3'
, то для обоих пользователей будет отображаться только сообщение Test2
. Как я могу получить «Test3» для отображения для обоих пользователей?
await MostRecentMessages.aggregate(
[
{
$match: {
$or: [
{ from: mongoose.Types.ObjectId(id) },
{ to: mongoose.Types.ObjectId(id) }
]
// deletedBy: { $ne: id }
}
},
{ $project: { _id: 1, from: 1, to: 1, conversation: 1, date: 1 } },
{ $sort: { date: -1 } },
{
$group: {
_id: {
userConcerned: {
$cond: {
if: {
$eq: ["$to", mongoose.Types.ObjectId(id)]
},
then: "$to",
else: "$from"
}
},
interlocutor: {
$cond: {
if: {
$eq: ["$to", mongoose.Types.ObjectId(id)]
},
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" } }
],
function(err, docs) {
if (err) {
console.log(err);
} else {
return res.json(docs);
}
}