嵌套localField时的$ lookup

时间:2018-07-03 17:40:37

标签: mongodb mongodb-query

MongoDB版本3.4.10 (应用程序正在使用Meteor框架)

目标:在运行时根据需要将_id引用的文档聚合到包含的文档中。

我有MaterialsModelsCatalog集合,其中包含以下文档:

材料

 { "_id" : "cf4KgXw7ZK6ukdzR7", "name" : "parquet_wood_mahogany" }

模型

{
  "_id" : "Mwp5eYYZ4GZzvZuoK",
  "name" : "top_square_chamfered",
  "type" : "top"
}
{
  "_id" : "CqhS2m2RcLZ2Bm4eb",
  "name" : "skirt_square",
  "type" : "skirt"
}
{
  "_id" : "dYP22ajALnWBwpBj2",
  "name" : "leg_square",
  "type" : "leg"
}

目录

{
  "_id" : "EcRGzPAq79giYKrbY",
  ...,
  "specs" : {
    ...,
    "models" : [
      {
        "mesh" : "Mwp5eYYZ4GZzvZuoK",
        "material" : "cf4KgXw7ZK6ukdzR7"
      },
      {
        "mesh" : "CqhS2m2RcLZ2Bm4eb",
        "material" : "cf4KgXw7ZK6ukdzR7"
      },
      {
        "mesh" : "dYP22ajALnWBwpBj2",
        "material" : "cf4KgXw7ZK6ukdzR7"
      }
    ]
  }
}

所需汇总后返回的文档格式:

{
  "_id" : "EcRGzPAq79giYKrbY",
  ...,
  "specs" : {
    "dimensions" : {
      ...,
    },
    "models" : [
      {
        "mesh" : {
          "_id" : "Mwp5eYYZ4GZzvZuoK",
          "name" : "top_square_chamfered",
          "type" : "top"
        },
        "material" : {
          "_id" : "cf4KgXw7ZK6ukdzR7",
          "name" : "parquet_wood_mahogany"
        }
      },
      {
        "mesh" : {
          "_id" : "CqhS2m2RcLZ2Bm4eb",
          "name" : "skirt_square",
          "type" : "skirt"
        },
        "material" : {
          "_id" : "cf4KgXw7ZK6ukdzR7",
          "name" : "parquet_wood_mahogany"
        }
      },
      {
        "mesh" : {
          "_id" : "dYP22ajALnWBwpBj2",
          "name" : "leg_square",
          "type" : "leg"
        },
        "material" : {
          "_id" : "cf4KgXw7ZK6ukdzR7",
          "name" : "parquet_wood_mahogany"
        }
      }
    ]
  }
}

我没有包含任何查询代码,因为它与实际情况相去甚远,以至于成为噪音。我一直在尝试将aggregate$lookup组合使用,但是我没有找到跟我想要的相近的东西。 MongoDB v3.6 pipeline语法将使此操作变得更加容易...但是在v3.4中我完全不知所措。

如果可能的话,我想避免使用多个数据库请求来组合此信息。任何建议的帮助将不胜感激!

编辑:有效的解决方案-

db.catalog.aggregate([
  { "$lookup": {
    "from": 'models',
    "localField": "specs.models.mesh",
    "foreignField": "_id",
    "as": "models.mesh"
  }},
  { "$lookup": {
    "from": 'materials',
    "localField": "specs.models.material",
    "foreignField": "_id",
    "as": "models.material"
  }},
  { "$unwind": "$models.mesh" },
  { "$unwind": "$models.material" },
  { "$group":{
    "_id": "$_id",
    "title": { "$first": "$title" },
    "desc": { "$first": "$desc" },
    "thumbnail": { "$first": "$thumbnail" },
    "createdBy": { "$first": "$createdBy" },
    "createdAt": { "$first": "$createdAt" },
    "specs": { "$first": "$specs" },
    "models": { "$push": "$models" }
  }},
  { "$project": {
    "_id": "$_id",
    "title": "$title",
    "desc": "$desc",
    "thumbnail": "$thumbnail",
    "createdBy": "$createdBy",
    "createdAt": "$createdAt",
    "specs.dimensions": "$specs.dimensions",
    "specs.models": "$models",
  }}
])

1 个答案:

答案 0 :(得分:2)

您可以尝试以下汇总

db.catalog.aggregate([
  { "$lookup": {
    "from": 'models',
    "localField": "specs.models.mesh",
    "foreignField": "_id",
    "as": "models.mesh"
  }},
  { "$lookup": {
    "from": 'materials',
    "localField": "specs.models.material",
    "foreignField": "_id",
    "as": "models.material"
  }},
  { "$unwind": "$models.mesh" },
  { "$unwind": "$models.material" },
  { "$group":{
    "_id": "$_id",
    "title": { "$first": "$title" },
    "desc": { "$first": "$desc" },
    "thumbnail": { "$first": "$thumbnail" },
    "createdBy": { "$first": "$createdBy" },
    "createdAt": { "$first": "$createdAt" },
    "specs": { "$first": "$specs" },
    "models": { "$push": "$models" }
  }},
  { "$project": {
    "title": "$title",
    "desc": "$desc",
    "thumbnail": "$thumbnail",
    "createdBy": "$createdBy",
    "createdAt": "$createdAt",
    "specs.dimensions": "$specs.dimensions",
    "specs.models": "$models",
  }}
])