使用猫鼬聚合对象的嵌套数组

时间:2020-01-23 22:51:13

标签: node.js mongoose

我有以下模型,我想在_id字段上查询特定用户,并用与用户模型中对应的_id字段匹配的必要数据填充inbox.messages数组,更重要的是,我还想对每条消息进行分组按“来自”字段并返回结果

const UserSchema = new Schema({
   username: {
        type: String,
        required: true,
    },

    blockedUsers: {
        users: [
            {
                userId: {type: Schema.Types.ObjectId, ref: 'User', required: true },
            }
        ]
    },
    favorites: {
        users: [
            {
                userId: {type: Schema.Types.ObjectId, ref: 'User', required: true },
            }
        ]
    },
    profileViews: {
        views: [
            {
                userId: {type: Schema.Types.ObjectId, ref: 'User', required: true },
                date: {type: Date}
            }
        ]
    },
    inbox: {
        messages: [
            {
                messageId: {type: Schema.Types.ObjectId},
                from: {type: Schema.Types.ObjectId, ref: 'User', required: true },
                content: {type: String, required: true},
                date: {type: Date}
            }
        ]
    },
    images: {
        "imagePaths": [
            {   
                imageId: {type: Schema.Types.ObjectId},
                path: { type: String, required: true},
                date: {type: Date}
            }
        ],
    }
})

我到目前为止有什么

  let incomingId = '5e29fd75fdfd5320d0e42bc4';
  let myUser = await User.aggregate([
           { $match: {"_id": mongoose.Types.ObjectId(incomingId) }},
           { $lookup: { }}
         ])

不确定是否要在$ lookup字段中输入什么内容,或者是否正确。

作为示例,我希望文档看起来像:

[
  {
    "from": "5e240f7480a24e07d832c7bd",
    "username":"hable0",
    "images": {
      imagePaths: [
         'images/2020-09-24-Z_34234342_12.jpg'
      ],
     },
    "inbox": {
      "messages": [
        {
          "messageId": "5e2a110a21c64d63f451e39e",
          "content": "Message content",
          "date": "2020-01-23T21:32:58.126Z"
        },
        {
          "messageId": "5e2a111321c64d63f451e3a0",
          "content": "Message content",
          "date": "2020-01-23T21:33:07.378Z"
        },
        {
          "messageId": "5e2a112321c64d63f451e3a2",
          "content": "Message content",
          "date": "2020-01-23T21:33:23.036Z"
        }
      ]
    }
  }
]

1 个答案:

答案 0 :(得分:0)

您可以使用aggregate()尝试以下管道。

  • 查找与ID匹配的文档
  • 放开inbox.messages
  • from字段分组
  • 执行$lookup以获得另一个文档
  • 执行$unwind破坏数组
  • 指定要包含在输出中的字段
let myUser = await User.aggregate([
  {
    $match: { "_id": mongoose.Types.ObjectId(incomingId) }
  },
  {
    $unwind: "$inbox.messages"
  },
  {
    $group: {
      _id: { from: "$inbox.messages.from" },
      messages: {
        $push: {
          messageId: "$inbox.messages.messageId"
          // Add more info of the message here as needed
        }
      }
    },
  },
  {
    $lookup: {
      from: "User",
      localField: "_id.from",
      foreignField: "_id",
      as: "extraUserInfo"
    }
  },
  {
    $unwind: "$extraUserInfo"
  },
  {
    $project: {
      _id: 0,
      from: "$_id.from",
      inbox: { messages: "$messages" },
      username: "$extraUserInfo.username",
      images: "$extraUserInfo.images"
    }
  }
]);

示例输出:

{
  "from": "user1",
  "inbox": {
    "messages": [{
      "messageId": "message1-from-user1"
    }]
  },
  "username": "user1-username",
  "images": {
    "imagePaths": ["image-path-user1"]
  }
} {
  "from": "user2",
  "inbox": {
    "messages": [{
      "messageId": "message1-from-user2"
    }, {
      "messageId": "message2-from-user2"
    }, {
      "messageId": "message3-from-user2"
    }]
  },
  "username": "user2-username",
  "images": {
    "imagePaths": ["image-path-user2"]
  }
} {
  "from": "user3",
  "inbox": {
    "messages": [{
      "messageId": "message1-from-user3"
    }, {
      "messageId": "message2-from-user3"
    }]
  },
  "username": "user3-username",
  "images": {
    "imagePaths": ["image-path-user3"]
  }
}

希望这能回答您的部分问题。尽管我不太清楚您想如何用发送消息的用户信息填充messages数组。但是您可以在$lookup()操作之后通过管道执行$group(),以将其他信息从发送者附加到结果。

详细了解$unwind$group$project$lookup