【问题标题】:Mongoose aggregate to group by parent id in the same documentMongoose 聚合在同一文档中按父 ID 分组
【发布时间】:2021-09-17 22:03:40
【问题描述】:

我在 mongoDB 呼叫公司中有一个简单的文档,其架构如下:

const companySchema = mongoose.Schema({
  _id: mongoose.Schema.Types.ObjectId,
  id: { type: String },
  name: { type: String },
  parentId: { type: String, default: null },
  type: { type: Number },
  active: { type: Boolean, default: true },
  number: { type: String },
});

然后我有一个查询来获取所有公司并按 parentId 将它们分组并将所有子公司添加到分支机构属性。

我在某种程度上完成了这项工作,但需要最后的努力才能获得所需的一切。

这是我目前的代码:


Company.aggregate([
    {
      $match: {
        active: true,
      },
    },

    {
      $project: {
        _id: { $cond: ['$parentId', '$parentId', '$id'] },
        name: 1,
        id: '$id',
        parent: '$parent',
        parentId: { $ifNull: ['$parentId', false] },
      },
    },

    { $sort: { _id: 1, parentId: -1 } },
    {
      $group: {
        _id: '$_id',
        name: { $min: { $cond: ['$parentId', '$name', false] } },
        branches: {
          $push: '$$ROOT',
        },
      },
    },
    {
      $project: {
        name: 1,
        branches: '$branches',
      },
    },
  ])

这是我目前得到的输出:

{
  "_id": "29689760",
  "name": "Branch 2",
  "branches": [
    { "name": "Test (Head Office)", "_id": "29689760", "id": "29689760", "parentId": false },
    { "name": "Branch 1", "_id": "29689760", "id": "29694015", "parentId": "29689760" },
    { "name": "Branch 2", "_id": "29689760", "id": "29694016", "parentId": "29689760" },
    { "name": "Branch 3", "_id": "29689760", "id": "29694017", "parentId": "29689760" },
    { "name": "Branch 4", "_id": "29689760", "id": "29694018", "parentId": "29689760" }
  ]
}

我需要的是返回所有关于母公司和分支机构以排除母公司的主要对象,即

{
  "_id": "29689760",
  "name": "Test (Head Office)"",
  "branches": [
//the next line will be missins
    //{ "name": "Test (Head Office)", "_id": "29689760", "id": "29689760", "parentId": false },
    { "name": "Branch 1", "_id": "29689760", "id": "29694015", "parentId": "29689760" },
    { "name": "Branch 2", "_id": "29689760", "id": "29694016", "parentId": "29689760" },
    { "name": "Branch 3", "_id": "29689760", "id": "29694017", "parentId": "29689760" },
    { "name": "Branch 4", "_id": "29689760", "id": "29694018", "parentId": "29689760" }
  ]
}

我尝试将$lookup 添加为聚合的第一个参数,但这会将信息添加到每个分支机构,而不仅仅是母公司。

有什么帮助吗?

【问题讨论】:

    标签: mongodb mongoose aggregation-framework


    【解决方案1】:

    _idparentId 中的条件处于$project$group 阶段时,您的查询会令人困惑,

    但根据你的说法,

    我需要的是返回所有关于母公司和分支机构以排除母公司的主要对象

    我会在您的查询中建议一个解决方案,您可以在$group 阶段更改此设置,

    • push 分支时设置条件,如果parentId 为false 则push root 文档,否则$$REMOVE 排除push
        {
          $group: {
            _id: '$_id',
            name: { $min: { $cond: ['$parentId', '$name', false] } },
            branches: {
              $push: {
                $cond: ['$parentId', '$$ROOT', '$$REMOVE']
              }
            },
          },
        },
    

    第二个选项可以使用$lookup 加入并从同一个集合中获取分支,

    • $match 你的必填字段和parentId 应该为空
    • $sort _id 按升序排列
    • $lookup 当前收藏
    • $project 显示必填字段
    await Company.aggregate([
      {
        $match: {
          active: true,
          parentId: null
        }
      },
      { $sort: { _id: 1 } },
      {
        $lookup: {
          from: 'company', // change your original collection name
          localField: 'id', 
          foreignField: 'parentId',
          as: 'branches'
        }
      },
      {
        $project: {
          _id: 0,
          name: 1,
          branches: {
            id: 1,
            name: 1,
            _id: 1,
            parentId: 1
          }
        }
      }
    ])
    

    Playground

    【讨论】:

    • 删除父项的条件非常有效。但是我在 $group 中遇到了 name 属性的问题。有没有办法将其作为母公司的名称而不是其中一个子公司的名称?谢谢
    • 你可以在playground 中发布示例文档并分享链接吗?
    • 您好,感谢您的帮助。我查看了您的答案并意识到我没有正确阅读它。现在一切正常。非常感谢:-)
    猜你喜欢
    • 2017-08-18
    • 1970-01-01
    • 2020-08-27
    • 2018-07-14
    • 2023-03-14
    • 1970-01-01
    • 2015-02-28
    • 2021-12-15
    • 2015-10-04
    相关资源
    最近更新 更多