如何在对象嵌套数组中进行$ lookup

时间:2020-08-10 13:12:53

标签: mongodb mongoose mongodb-query

我必须有两个集合,一个是旅行团,另一个是目的地,所以在旅行团中我有一个位置数组,其中有一个带id的目的地对象,而id属于另一个目的地集合,但事实是我无法在位置数组中查找目的地的详细信息。每个人也尝试过许多查询搜索。但没有得到预期的结果。

游览:

{
    "_id" : ObjectId("5f3122f4d8d57e3b9650e5b4"),
    "title" : "tour 1",
    "locations" : [ 
        {
            "destination" : {
                "id" : "5ec5ae9037ea99f20a79071a"
            },
            "services" : {
                "hotel" : true
            }
        }, 
        {
            "destination" : {
                "id" : "5ec5ae8e37ea99f20a78ef8c"
            },
            "services" : {
                "hotel" : true
            }
        }
    ]
}
{
    "_id" : ObjectId("5f2d65e68bc6e9155310d147"),
    "title" : "tour 2",
    "locations" : [ 
        {
            "destination" : {
                "id" : "5ecf994435c3a6025d5bf126"
            },
            "services" : {
                "hotel" : true
            }
        }
    ]
}
{
    "_id" : ObjectId("5f2d66398bc6e9155310d161"),
    "title" : "tour 3",
    "locations" : [ 
        {
            "destination" : {
                "id" : "5ec5ae8e37ea99f20a78ef8d"
            },
            "services" : {
                "hotel" : true
            }
        }
    ]
}

目的地:

{
    "_id" : ObjectId("5ec5ae9037ea99f20a79071a"),
    "name" : "dest 1",
    "country" : "country name"
}
{
    "_id" : ObjectId("5ec5ae8e37ea99f20a78ef8c"),
    "name" : "dest 2",
    "country" : "country name"
}
{
    "_id" : ObjectId("5ec5ae8e37ea99f20a78ef8d"),
    "name" : "dest 3",
    "country" : "country name"
}
{
    "_id" : ObjectId("5ecf994435c3a6025d5bf126"),
    "name" : "dest 4",
    "country" : "country name"
}

预期结果:

{
    "_id" : ObjectId("5f3122f4d8d57e3b9650e5b4"),
    "title" : "tour 1",
    "locations" : [ 
        {
            "destination" : {
                "id" : "5ec5ae9037ea99f20a79071a",
                "name" : "dest 1",
                "country" : "country name"
            },
            "services" : {
                "hotel" : true
            }
        }, 
        {
            "destination" : {
                "id" : "5ec5ae8e37ea99f20a78ef8c",
                "name" : "dest 2",
                "country" : "country name"
            },
            "services" : {
                "hotel" : true
            }
        }
    ]
},
{
    "_id" : ObjectId("5f2d65e68bc6e9155310d147"),
    "title" : "tour 2",
    "locations" : [ 
        {
            "destination" : {
                "id" : "5ecf994435c3a6025d5bf126",
                "name" : "dest 4",
                "country" : "country name"
            },
            "services" : {
                "hotel" : true
            }
        }
    ]
},
{
    "_id" : ObjectId("5f2d66398bc6e9155310d161"),
    "title" : "tour 3",
    "locations" : [ 
        {
            "destination" : {
                "id" : "5ec5ae8e37ea99f20a78ef8d",
                "name" : "dest 3",
                "country" : "country name"
            },
            "services" : {
                "hotel" : true
            }
        }
    ]
}

尝试查询:

db.tours.aggregate([
  { 
    "$addFields": {
      "locations": {
        "$map": {
          "input": "$locations",
          "in": {
            "$mergeObjects": [
              "$$this",
              {
                "dest_oid": {
                  "$toObjectId": "$$this.destination.id"
                }
              }
            ]
          }
        }
      }
    }
  },
  { "$unwind": "$locations" },

  { "$lookup": {
    "from": "destinations",
    "localField": "locations.dest_oid",
    "foreignField": "_id",
    "as": "locations.dest",
  }},
  { "$unwind": "$locations.dest" },
  { "$group": {
    "_id": "$_id",
    "locations": { "$push": "$locations" }
  }}
])

即使我尝试过 MongoDB $lookup on nested document

2 个答案:

答案 0 :(得分:0)

快速修复,

  • $unwind locations数组放在第一位,因为需要将id转换为对象id
db.tours.aggregate([
  { $unwind: "$locations" },
  • 如果您已经将字符串ID转换为对象ID,请跳过此部分
  • $addFields替换locations.destination.id到对象ID,过滤掉您的逻辑,因此这里不需要$ map和$ mergeObjects选项
  {
    $addFields: {
      "locations.destination.id": {
        $toObjectId: "$locations.destination.id"
      }
    }
  },
  • $lookup您已经做过,但更改为locations.destination
  {
    $lookup: {
      from: "destinations",
      as: "locations.destination",
      localField: "locations.destination.id",
      foreignField: "_id"
    }
  },
  • $ unwind locations.destination是因为它的数组,我们需要对象
  {
    $unwind: {
      path: "$locations.destination"
    }
  },
  • $group,您已经做过,更改很少,将第一个目的地和服务推送到位置并添加了第一个标题
  {
    $group: {
      _id: "$_id",
      locations: { $push: "$locations" },
      title: { $first: "$title" }
    }
  }
])

游乐场:https://mongoplayground.net/p/yaTCij7NRUj

答案 1 :(得分:-1)

如果可以将string集合中的destination.id Tours转换/更新为ObjectId(如果尚未更新)。以下查询应该有效。

查询:

db.Tours.aggregate([
  {
    $unwind: "$locations",
  },
  {
    $lookup: {
      from: "Destinations",
      localField: "locations.destination.id",
      foreignField: "_id",
      as: "destination",
    },
  },
  {
    $project: {
      title: "$title",
      locations: {
        destination: {
          $arrayElemAt: ["$destination", 0],
        },
        services: "$locations.services",
      },
    },
  },
  {
    $group: {
      _id: "$_id",
      title: {
        $first: "$title",
      },
      locations: {
        $push: "$locations",
      },
    },
  },
]);

Playground Link