简体   繁体   English

Mongodb 填充聚合字段

[英]Mongodb populate aggregated field

I want to use $lookup for joining 3 different collections in mongoDB, and populate a ref array with the coresponding data of the ref which is the client collection.我想使用 $lookup 在 mongoDB 中加入 3 个不同的 collections,并使用作为客户端集合的 ref 的对应数据填充一个 ref 数组。

Conversation:对话:

{
  _id: mongoose.Schema.Types.ObjectId,
  participants: [{ type: mongoose.Schema.Types.ObjectId, ref: "client" }],
  created_at: { type: Date, default: Date.now },
}

Message:信息:

{
  _id: mongoose.Schema.Types.ObjectId,
  conversation_id: { type: mongoose.Schema.Types.ObjectId, ref: "Conversation",
  message: { type: String, default: "" },
  sender: {type: mongoose.Schema.Types.ObjectId,ref: "Client",default: null},
  reciever: {type: mongoose.Schema.Types.ObjectId,ref: "Client",default: null,},
  created_at: { type: Date, default: Date.now }
}

Client:客户:

{
  _id: mongoose.Schema.Types.ObjectId,
  email: {type: String, required: true, unique: true},
  name: { type: String, default: "" },
  job: { type: String, default: "" },
  company: { type: String, default: "" },
  school: { type: String, default: "" },
}

Here is what i am usgin now without the populate:这是我现在在没有填充的情况下使用的内容:

  Conversation.aggregate([
    { $match: { participants: { $all: [mongoose.Types.ObjectId(myId)] } } },
    {
      $lookup: {
        from: "messages",
        localField: "_id",
        foreignField: "conversation_id",
        as: "messages",
      },
    },
    {
      $unwind: { path: "$messages", preserveNullAndEmptyArrays: true },
    },
    { $sort: { "messages.created_at": -1 } },
    {
      $group: {
        _id: "$_id",
        messages: { $first: "$messages" },
        doc: { $first: "$$ROOT" },
      },
    },
    { $replaceRoot: { newRoot: "$doc" } },
  ])

This is the result i get:这是我得到的结果:

[
 {
  "_id": "5f29ca6fc410a01e6fd53ca1",
  "participants": [
   "5f1c4685546a7741b8c6e801",
   "5f1c80d1f52da506603278f1"
  ],
  "messages": {
   "_id": "5f2aff3715db59002458f650",
   "message": "Thanks man",
   "sender": "5f1c80d1f52da506603278f1",
   "reciever": "5f1c4685546a7741b8c6e801",
   "conversation_id": "5f29ca6fc410a01e6fd53ca1",
   "created_at": "2020-08-05T18:49:27.752Z",
   "__v": 0
  }
 },
 {
  "_id": "5f29c944c410a01e6fd4aa2b",
  "participants": [
   "5f1c4685546a7741b8c6e801",
   "5f05d5e20db0174bd4b55b29"
  ]
 }
]

I want to populate the participants array when i aggregate the conversation with message .当我用message聚合对话时,我想填充参与者数组。

Thank you.谢谢你。

Using aggregate() ,使用聚合()

  • here you can use lookup with pipeline , it can to add all pipelines lookup level,在这里您可以使用管道查找,它可以添加所有管道查找级别,

  • no need to $unwind and $group无需 $unwind 和 $group

Conversation.aggregate([
  {
    $match: {
      participants: {
        $all: [
          mongoose.Types.ObjectId(myId)
        ]
      }
    }
  },
  • lookup for messages查找消息
  {
    $lookup: {
      from: "Message",
      let: {
        conversation_id: "$_id"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $eq: [
                "$$conversation_id",
                "$conversation_id"
              ]
            }
          }
        },
        {
          $sort: {
            "created_at": -1
          }
        }
      ],
      as: "messages"
    }
  },
  • lookup for participants查找参与者
  {
    $lookup: {
      from: "Client",
      let: {
        participants: "$participants"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $in: [
                "$_id",
                "$$participants"
              ]
            }
          }
        },
        {
          $sort: {
            "created_at": -1
          }
        }
      ],
      as: "participants"
    }
  }
])

Playground: https://mongoplayground.net/p/Pz5ojJ_dGGY游乐场: https://mongoplayground.net/p/Pz5ojJ_dGGY

Note: I have assumed the name of the collections so you can correct and change as per your requirement.注意:我假设了 collections 的名称,因此您可以根据您的要求进行更正和更改。

this is the code i got, i changed the id to string only:这是我得到的代码,我将 id 更改为仅字符串:

Conversation.aggregate([
    { $match: { participants: { $all: [mongoose.Types.ObjectId(myId)] } } },
    {
      $lookup: {
        from: "messages",
        let: { conversationId: { $toObjectId: "$_id" }},
        pipeline: [
          {
            $match: { $expr: {$eq: ["$$conversationId", "$conversation_id"]}},
          },
          {
            $sort: { create_at: -1 },
          },
          { $limit: 1 },
        ],
        as: "messages",
      },
    },
    {
      $lookup: {
        from: "clients",
        let: {participants: "$participants"},
        pipeline: [
          {
            $match: {
              $expr: {
                $and: [
                  { $in: ["$_id", "$$participants"] },
                  { $ne: ["$_id", mongoose.Types.ObjectId(myId)] },
                ]},
            },
          },
          {
            $sort: { created_at: -1 },
          },
        ],
        as: "participants",
      },
    },
    {
      $project: {
        _id: 1,
        messages: 1,
        "participants.name": 1,
        "participants.company": 1,
        "participants.school": 1,
      },
    },
  ])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM