【问题标题】:Mongo $lookup nested array 3 levels deep using mongooseMongodb $lookup 嵌套数组 3 层使用 mongoose
【发布时间】:2019-06-18 02:37:20
【问题描述】:

我在outsideServices 模型里面有这个:

name: String,
salary: Number,
services: [
      {
        category: {
          ref: 'ServiceCategories',
          type: Schema.Types.ObjectId
        },
        types: [
          {
            ref: 'ServiceType',
            type: Schema.Types.ObjectId
          }
        ]
      }
    ]

我在incidents 模型里面有这个:

  outsideServices: {
      ref: 'OutsideService',
      type: Schema.Types.ObjectId
    }

所以当从 api 请求 incidents 时,响应会是这样的:

[
  {
    category: '5cf655135a1b72106777c238',
    types: ['5cf655a85a1b72106777c239']
  },
  {
    category: '5cf656525a1b72106777c23b',
    types: ['5cf656835a1b72106777c23c']
  }
];

如何查找categoriestypes ref 并在我的回复中保留上面的结构?

这是我迄今为止尝试过的,但我无法得到想要的结果:

aggregate.lookup({
      from: 'outsideservices',
      let: { serviceId: '$outsideServices' },
      pipeline: [
        { $match: { $expr: { $eq: ['$_id', '$$serviceId'] } } },
        {
          $lookup: {
            from: 'servicecategories',
            let: { services: '$services.category' },
            pipeline: [{ $match: { $expr: { $in: ['$_id', '$$services'] } } }],
            as: 'category'
          }
        },
        {
          $lookup: {
            from: 'servicetypes',
            let: { services: '$services.types' },
            pipeline: [
              { $match: { $expr: { $in: ['$_id', '$$services'] } } }
            ],
            as: 'types'
          }
        }
      ],
      as: 'outsideService'
    });

想要的结果/结果与上面的响应类似,但包含填充文档而不是 ObjectIds

MongoDB版本4.0.10

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    您可以尝试以下聚合。使用 $unwind 解构数组,然后使用 $lookup 提取类别和类型,最后使用 $group 返回原始结构。

    {
      "from":"outsideservices",
      "let":{"serviceId":"$outsideServices"},
      "pipeline":[
        {"$match":{"$expr":{"$eq":["$_id","$$serviceId"]}}},
        {"$unwind":"$services"},
        {"$lookup":{
        "from":"servicecategories",
        "localField":"services.category",
        "foreignField":"_id",
        "as":"services.category"
        }},
        {"$lookup":{
        "from":"servicetypes",
        "localField":"services.types",
        "foreignField":"_id",
        "as":"services.types"
        }},
        {"$group":{
        "_id":null,
        "services":{"$push":"$services"}
        }}
      ],
      "as":"outsideService"
    }
    

    【讨论】:

    • 感谢您的回复,如果我想保留整个文档而不仅仅是回复中的{_id: null, services: [...] ,我该怎么办?我试过{ $group: { _id: null, services: { $push: '$services' }, doc: { $first: '$$ROOT' } } }, { $replaceRoot: { newRoot: '$doc' } },但这只会返回一项服务(因为$first应该如此)。
    • 不客气。在您的组和 replaceRoot 阶段之间插入{$addFields:{“doc.services”:”$services”}}。你问的是这个吗?
    • 我已经更新了问题,services 架构有更多属性,而不仅仅是服务。我也想在聚合后保留它们。我可以$group 使用$first 和在下一阶段$project 他们,但我还有五个refs 我需要使用相同的代码查找和分组,这需要这么多代码,它们是大对象,我希望有更简单的方法。
    • 对不起,我没关注你。 addFields 阶段在改变/创建阶段中的字段时保留现有字段。要查找,您必须一次做一次,没有捷径可走。看看你能不能用更多的细节更新问题,我可以试一试。
    【解决方案2】:

    因此,您使用的是 mongoose 架构,但随后使用 mongoDB 进行聚合。

    您需要使用populate,它是来自mongoosematch stage

    populate 是你的refs 等等。

    【讨论】:

    • 感谢您的回复,我需要使用聚合,因为在到达此阶段之前我会进行更多查询,aggregate.lookup({}) 正在使用 mongoose,我不太明白您为什么指出我使用 mongoose然后下到 mongoDB。
    猜你喜欢
    • 2018-10-06
    • 1970-01-01
    • 2019-03-20
    • 1970-01-01
    • 1970-01-01
    • 2018-08-16
    • 1970-01-01
    • 2022-09-29
    • 2016-02-09
    相关资源
    最近更新 更多