【问题标题】:aggregate nested array of objects using mongoose使用猫鼬聚合嵌套的对象数组
【发布时间】:2020-05-10 07:01:10
【问题描述】:

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

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"
        }
      ]
    }
  }
]

【问题讨论】:

  • 您能否edit 您的问题包括一些示例文档以与您预期的 JSON 输出一起进行测试?

标签: node.js mongoose


【解决方案1】:

您可以使用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 数组。但是您可以在$group() 操作之后使用管道执行$lookup(),以将来自发件人的其他信息附加到结果中。

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

【讨论】:

  • 是的,这开始看起来像我想要的,但我在 User 模型和 imagePaths 字段上也有一个用户名字段,我也想抓住这些并放入信息。你能举一个执行 $lookup 的例子吗?我还是不太明白。
  • @WoodsD 我更新了我的答案以包含$lookup。让我知道这是否适合您。
  • 现在我得到一个空数组。在您显示结果之前,我在哪里得到结果
  • 哦,也许有错字。我正在查找Users 而不是User。请帮我检查所有变量名称以确保它们是正确的,因为我没有像你这样的完整设置。顺便更新了答案。
  • 我检查并更改了用户从用户。这也无济于事,因为这是一个自我参考。我是否应该考虑调整文档结构并将这些数据放入单独的集合中?
猜你喜欢
  • 2021-04-14
  • 2020-06-12
  • 1970-01-01
  • 2015-08-21
  • 1970-01-01
  • 2021-07-22
  • 1970-01-01
  • 1970-01-01
  • 2021-05-06
相关资源
最近更新 更多