【问题标题】:mongodb how to use aggregate like populatemongodb如何使用聚合之类的填充
【发布时间】:2020-04-18 03:27:02
【问题描述】:

代码示例在 Mongo Playground

https://mongoplayground.net/p/W4Qt4oX0ZRP

假设以下文件

[
  {
    _id: "5df1e6f75de2b22f8e6c30e8",
    user: {
      name: "Tom",
      sex: 1,
      age: 23
    },
    dream: [
      {
        label: "engineer",
        industry: "5e06b16fb0670d7538222909",
        type: "5e06b16fb0670d7538222951",

      },
      {
        label: "programmer",
        industry: "5e06b16fb0670d7538222909",
        type: "5e06b16fb0670d7538222951",

      }
    ],
    works: [
      {
        name: "any engineer",
        company: "5dd7fd51b0ae1837a08d00c8",
        skill: [
          "5dc3998e2cf66bad16efd61b",
          "5dc3998e2cf66bad16efd61e"
        ],

      },
      {
        name: "any programmer",
        company: "5dd7fd9db0ae1837a08d00e2",
        skill: [
          "5dd509e05de2b22f8e67e1b7",
          "5dd509e05de2b22f8e67e1bb"
        ],

      }
    ]
  }
]

我尝试使用aggregate $lookup $unwind

db.coll.aggregate([
  {
    $unwind: {
      path: "$dream",

    }
  },
  {
    $lookup: {
      from: "industry",
      localField: "dream.industry",
      foreignField: "_id",
      as: "dream.industry"
    },

  },
  {
    $unwind: {
      path: "$dream.industry",

    }
  },
  {
    $lookup: {
      from: "type",
      localField: "dream.type",
      foreignField: "_id",
      as: "dream.type"
    },

  },
  {
    $unwind: {
      path: "$dream.type",

    }
  },
  {
    $unwind: {
      path: "$works",

    }
  },
  {
    $lookup: {
      from: "company",
      localField: "works.company",
      foreignField: "_id",
      as: "works.company"
    },

  },
  {
    $unwind: {
      path: "$works.company",

    }
  },
  {
    $lookup: {
      from: "skill",
      localField: "works.skill",
      foreignField: "_id",
      as: "works.skill"
    },

  },

])

执行上述代码并没有得到想要的结果!

这是我所期望的

{
  _id: "5df1e6f75de2b22f8e6c30e8",
  user: {
    name: 'Tom',
    sex: 1,
    age: 23
  },
  dream: [
    {
      label: 'engineer',
      industry: {
        _id: "5e06b16fb0670d7538222909",           // Industry doc _id
        name: 'IT',
        createdAt: "2019-12-28T01:35:44.070Z",
        updatedAt: "2019-12-28T01:35:44.070Z"
      },
      type: {
        _id: "5e06b16fb0670d7538222951",           // Type doc _id
        name: 'job',
        createdAt: "2019-12-28T01:35:44.070Z",
        updatedAt: "2019-12-28T01:35:44.070Z"
      },
    },
    {
      label: 'programmer',
      industry: {
        _id: "5e06b16fb0670d7538222909",           // Industry doc _id
        name: 'IT',
        createdAt: "2019-12-28T01:35:44.070Z",
        updatedAt: "2019-12-28T01:35:44.070Z"
      },
      type: {
        _id: "5e06b16fb0670d7538222951",           // Type doc _id
        name: 'job',
        createdAt: "2019-12-28T01:35:44.070Z",
        updatedAt: "2019-12-28T01:35:44.070Z"
      }
    }
  ],
  works: [
    {
      name: 'any engineer',
      company: {
        _id: "5dd7fd51b0ae1837a08d00c8",          // Company doc _id
        name: 'alibaba',
        area: 'CN',
      },
      skill: [
        { 
          _id: "5dc3998e2cf66bad16efd61b",        // Skill doc _id
          name: 'Java' 
        }, 
        { 
          _id: "5dc3998e2cf66bad16efd61e",        // Skill doc _id
          name: 'Php' 
        }, 
      ]
    },
    {
      name: 'any programmer',
      company: {
        _id: "5dd7fd9db0ae1837a08d00e2",           // Company doc _id
        name: 'microsoft',
        area: 'EN',
      },
      skill: [
        { 
          _id: "5dd509e05de2b22f8e67e1b7",           // Skill doc _id
          name: 'Golang' 
        },
        { 
          _id: "5dd509e05de2b22f8e67e1bb",         // Skill doc _id
          name: 'Node.js'
        }
      ]
    },
  ]
}

预期的结果是dream是一个数组,works是一个数组,而dream.industry从ObjectId变成了document,dream.type从ObjectId变成了document,works.company从ObjectId变成了document

当我使用填充时,我可以轻松地做到这一点

Model.find()
 .populate('dream.industry')
 .populate('dream.type')
 .populate('works.company')
 .populate('works.skill')
 .lean()

我参考以下问题

  1. mongoose aggregate lookup array(和我的问题差不多,但没有解决)
  2. $lookup on ObjectId's in an array

希望能得到大家的帮助,谢谢!

【问题讨论】:

  • 您需要在示例文档中提供真实的 ObjectId 值,以方便我们使用。更好的是在mongoplayground.net创建一个示例@
  • 你当前代码的结果是什么?注意MongoDB对象ids必须保存为ObjectId,例如:行业:ObjectId("5e06b16fb0670d7538222909"),如果将mongo ids保存为字符串,则查找阶段不起作用。
  • @Amin Shojaei,谢谢!当前代码的结果在mongoplayground.net/p/W4Qt4oX0ZRP
  • 老实说,我试图了解当前结果和您的预期结果有何不同,但我无法弄清楚。
  • 预期的结果是dream是一个数组,works是一个数组,dream.industry从ObjectId变成了document,dream.type从ObjectId变成了document,works.company从ObjectId 到文档

标签: mongodb mongoose nosql


【解决方案1】:

为了更容易,我不会更改当前管道,而只是在其末尾添加一个 $group 阶段以重新构造数据。

{
    $group: {
        _id: "$_id",
        user: {$first: "$user"},
        dream: {$addToSet: "$dream"},
        works: {$addToSet: "$works"}
    }
}

话虽如此,如果您使用的是 Mongo 3.6+ 版,我确实建议您使用 $lookup 的“较新”版本来重写您的管道,从而避免所有这些 $unwind 以提高效率。

【讨论】:

  • 非常感谢@tomslabbaert 的回答,是的,它是3.6+ 版本,如何使用$lookup 的“较新”版本来重写我的管道?
猜你喜欢
  • 2021-10-22
  • 2021-04-25
  • 1970-01-01
  • 2021-04-21
  • 1970-01-01
  • 2017-11-06
  • 2019-10-25
  • 1970-01-01
  • 2020-08-19
相关资源
最近更新 更多