嵌套数组字段上的 Mongodb 聚合查找覆盖其他字段



这是我收藏的详细信息,我有 4 个收藏。

Chat,
ChatUser,
Messages,
User

这些集合的字段是,

Chat:
_id,
type ('dual', 'group')
ChatUser:
_id,
userId (Ref: Users)
chatId (Ref: Chat)
Messages:
_id,
chatId (Ref: Chat)
fromUserId (Ref: Chat)
type: ('text', 'media')
message
Users:
_id,
name,
avatar

我写了一个聚合函数来收集下面的所有聊天记录。

let chats = await Chat.aggregate([
{$match: {_id: {$in: chatsOfUser}}},
{
$lookup: {
from: "chatusers",
let: {cId: "$_id"},
pipeline: [
// <-- Added Pipeline
{
$match: {
$expr: {
$and: [
{$eq: ["$chatId", "$$cId"]},
{$ne: ["$userId", mongoose.Types.ObjectId(req.user._id)]},
],
},
},
},
],
as: "ChatUser",
},
},
{$unwind: "$ChatUser"},
{$unwind: "$ChatUser.userId"},
{
$lookup: {
from: "users",
localField: "ChatUser.userId",
foreignField: "_id",
as: "Users",
},
},
{$unwind: "$Users"},
{$project: {"Users.password": 0}},
{
$lookup: {
from: "messages",
localField: "_id",
foreignField: "chatId",
as: "Messages",
},
},
{$sort: {"Messages.createdAt": -1}},
]);

我的实际结果是,

{
"chats": [
{
"_id": "60db388deb35c276cd023f32",
"type": "dual",
"ChatUser": {
"_id": "60db388deb35c276cd023f36",
"chatId": "60db388deb35c276cd023f32",
"userId": "60db387feb35c276cd023f1f",
},
"Users": {
"_id": "60db387feb35c276cd023f1f",
"firstName": "Frodo",
"lastName": "Baggins",
"email": "Frodo.Baggins@gmail.com",
"gender": "male",
},
"Messages": [
{
"_id": "60db38f729d01c669696cb9e",
"message": "Hello friend",
"type": "text",
"chatId": "60db388deb35c276cd023f32",
"fromUserId": "60daeb5617b93e6cb968582e",// Here I want to populate the User name and avatar into a User Field
},
{
"_id": "60db38f729d01c669696cb9f",
"message": "Hi buddy",
"type": "text",
"chatId": "60db388deb35c276cd023f32",
"fromUserId": "60db387feb35c276cd023f1f", // Here I want to populate the User name and avatar into a User Field
}
]
},
]
}

在这里,我想在"chats.Messages.User"中填充"fromUserId"的用户详细信息。但是如果我使用以下查找,它会用新的用户对象替换消息的所有字段。在排序管道之前使用它。

{
$lookup: {
from: "users",
let: { user_id: "$Messages.fromUserId" },    
pipeline : [
{ $match: { $expr: { $eq: [ "$_id", "$$user_id" ] } }, },
{ $project : { _id:1, firstName:1 } }
],
as: "Messages.User"
}
},

在上述查找之前使用过放卷管道,

{ "$unwind": "$Messages" },
{ "$unwind": "$Messages.fromUserId" },

但它通过消息展开了整个聊天数组。我真的想只在chats.Messages.User'中提取fromUserId。有没有解决这个问题的解决方案?

有多种方法可以解决此问题,我选择我认为最简单的方法,而无需过多地更改现有管道。

我会更改消息中的第二个$lookup,以在其中包含一个嵌套$lookup以获取用户。这样我们就不需要展开整个文档并在之后重组数据。

它看起来像这样:

{
$lookup: {
from: "messages",
let: {
id: "$_id"
},
pipeline: [
{
$match: {
$expr: {
$eq: [
"$$id",
"$chatId"
]
}
}
},
{
$lookup: {
from: "users",
localField: "fromUserId",
foreignField: "_id",
as: "User"
}
},
{
$unwind: "$User"
},
{
$project: {
"User.password": 0
}
},

],
as: "Messages",

},

},

完整示例位于:

蒙戈游乐场

最新更新