【问题标题】:How to use variables with MongoDB $lookup如何在 MongoDB $lookup 中使用变量
【发布时间】:2017-03-29 20:24:56
【问题描述】:

假设我有 3 个集合,carsbikesvehicles

cars收藏为:

{
  {
    "_id": "car1",
    "carBrand": "Audi",
    "color": "blue"
  },
  {
    "_id": "car2",
    "carBrand": "BMW",
    "color": "white"
  }
}

bikes收藏为:

{
  {
    "_id": "bike1",
    "bikeBrand": "Audi",
    "color": "red"
  },
  {
    "_id": "bike2",
    "carBrand": "BMW",
    "color": "white"
  }
}

vehicles 集合实际上只是引用了carsbikes 集合作为

{
  {
    "_id": "vehicle1",
    "vehicleType": "cars",
    "vehicleId": "car1"
  },
  {
    "_id": "vehicle2",
    "vehicleType": "cars",
    "vehicleId": "car2"
  },
  {
    "_id": "vehicle3",
    "vehicleType": "bikes",
    "vehicleId": "bike1"
  },
  {
    "_id": "vehicle4",
    "vehicleType": "bikes",
    "vehicleId": "bike2"
  },

}

我想与carsbikes 集合一起加入vehicles 集合。我试图将"$vehicleType" 设置为$lookupfrom 字段的变量。但是它并没有像我预期的那样工作。它根本不加入表格。没有错误。

db.collection.aggregate([{

  $lookup: {
      from: "$vehicleType",
      localField: "vehicleId",
      foreignField: "_id",
      as: "vehicleDetails"
  }

}]);

我期待有这样的结果

{
  {
    "_id": "vehicle1",
    "vehicleType": "cars",
    "vehicleId": "car1",
    "vehicleDetails": {    
      "_id": "car1",
      "carBrand": "Audi",
      "color": ""
    }
  },
  {
    "_id": "vehicle2",
    "vehicleType": "cars",
    "vehicleId": "car2",
    "vehicleDetails":    {
      "_id": "car2",
      "carBrand": "BMW",
      "color": "white"

  },
  {
    "_id": "vehicle3",
    "vehicleType": "bikes",
    "vehicleId": "bike1",
    "vehicleDetails":    {
      "_id": "bike1",
      "bikeBrand": "Audi",
      "color": "red"
    }
  },
  {
    "_id": "vehicle4",
    "vehicleType": "bikes",
    "vehicleId": "bike2",
    "vehicleDetails":    {
      "_id": "bike2",
      "carBrand": "BMW",
      "color": "white"
    }
  },

}    

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

    如果汽车和自行车没有共同的 ID,您可以在单独的数组中顺序查找,然后将它们与 $setUnion 组合:

    db.vehicles.aggregate([
      {$lookup: {
          from: "cars",
          localField: "vehicleId",
          foreignField: "_id",
          as: "carDetails"
      }},
      {$lookup: {
          from: "bikes",
          localField: "vehicleId",
          foreignField: "_id",
          as: "bikeDetails"
      }},
      {$project: {
         vehicleType: 1,
         vehicleId: 1,      
         vehicleDetails:{$setUnion: [ "$carDetails", "$bikeDetails" ]}
      }},
      {$project: {
          carDetails:0,
          bikeDetails:0,
      }}
    ]);
    

    否则,您需要在查找前使用$facet 按类型过滤车辆:

    db.vehicles.aggregate([
       {
         $facet: {
             "cars": [
                {$match: {"vehicleType": "cars"}},
                {$lookup: {
                   from: "cars",
                   localField: "vehicleId",
                   foreignField: "_id",
                   as: "vehicleDetails"
                 }},
             ],
             "bikes": [
                {$match: {"vehicleType": "bikes"}},
                {$lookup: {
                   from: "bikes",
                   localField: "vehicleId",
                   foreignField: "_id",
                   as: "vehicleDetails"
                 }}
             ]
         }
       },
       {$project: {all: {$setUnion: ["$cars", "$bikes"]}}},
       {$unwind: "$all"},
       {$replaceRoot: { newRoot: "$all" }}
    ])
    

    【讨论】:

    • 谢谢。性能怎么样?我想,这将加入carsbikes 集合,而不管vehicleType。有没有办法在$lookup之前根据vehicleType进行过滤?
    • 是的,正如我所说,在更一般的情况下,您需要使用构面。我已经用代码 sn-p 更新了答案。
    猜你喜欢
    • 2019-10-24
    • 1970-01-01
    • 2019-11-02
    • 2020-07-12
    • 1970-01-01
    • 2020-08-12
    • 2021-09-21
    • 2020-06-04
    • 1970-01-01
    相关资源
    最近更新 更多