在多种情况下使用MongoDB合并多个文档

时间:2018-10-14 08:24:03

标签: mongodb

我遵循了下面的SO线程,但仍然无法正常工作。

MongoDB Join on multiple fields [duplicate]

Multiple join conditions using the $lookup operator

我的collection1如下:

{ 
   _id: 5bc2e44a106342152cd83e97,
   description:
            { 
              status: 'Good',
              machine: 'X',
             },
   order: 'A',
   lot: '1' 
}

我的collection2如下:

{
   _id: 5bc2e44a106342152cd83e80,
   isCompleted: false,
   serialNo: '1',
   batchNo: '2',
   product: [{ 
              order: 'A', lot: '1',
              order: 'A', lot: '2'
            }]
}

我期望的结果如下:

{ 
   _id: 5bc2e44a106342152cd83e97,
   description:
            { 
              status: 'Good',
              machine: 'X',
             },
   order: 'A',
   lot: '1' ,
   isCompleted: false,
   serialNo: '1',
   batchNo: '2'
}

聚合操作必须基于以下条件:product中的collection2数组包含orderlotorder相同和lot中的collection1

以下是我尝试的2个代码,但均无济于事。请给我一些指导。

db.collection2.aggregate([
              { $unwind : "$product" }
              {
                    $lookup: {
                          from: "collection1",
                          localField: "product.order",
                          foreignField: "order",
                          as: "results"
                    }
              },
              {
                    $replaceRoot: { newRoot: { $mergeObjects: [ { $arrayElemAt: [ "$results", 0 ] }, "$$ROOT" ] } }
              }]

然后,我尝试了基于文档的多重联接条件,但是没有运气

db.collection2.aggregate([
              { $unwind : "$product" },
              { $lookup: {
                     from: "collection1",
                     let: { order: "$order", lot: "$lot" },
                     pipeline: [
                           {
                                 $match: {
                                       $expr: {
                                             $and: [
                                                   { $eq: [ "$product.order", "$$order" ] },
                                                   { $eq: [ "$product.lot", "$$lot"] }
                                                   ]
                                             }
                                       }
                                 }
                           ],
                           as: "results"
                     }
               },
              {
                    $replaceRoot: { newRoot: { $mergeObjects: [ { $arrayElemAt: [ "$results", 0 ] }, "$$ROOT" ] } }
              }]

任何提示,指导或解决方案将不胜感激!谢谢!

2 个答案:

答案 0 :(得分:0)

您快到了,只是与查找中引用字段的一小部分混合在一起:

{
    from: "collection1",
    let: { order: "$product.order", lot: "$product.lot" },
    pipeline: [
       {
         $match: {
                  $expr: {
                          $and: [
                                 { $eq: [ "$order", "$$order" ] },
                                 { $eq: [ "$lot", "$$lot"] }
                                ]
                          }
                 }
       }],
    as: "results"
}

这将适用于u:)

答案 1 :(得分:0)

假设您的文档结构如下:

{
    _id: 5bc2e44a106342152cd83e80,
    isCompleted: false,
    serialNo: '1',
    batchNo: '2',
    product: [ // note the subdocuments here
        { order: 'A', lot: '1' },
        { order: 'A', lot: '2' }
    ]
}

您可以运行此命令以获得所需的结果:

db.collection1.aggregate([{
    $lookup: {
        from: "collection2",
        let: { order: "$order", lot: "$lot" },
        pipeline: [{
            $match: {
                $expr:  { $in: [ { order: "$$order", lot: "$$lot" }, "$product"] }
            }
        }],
        as: "isCompleted" // we're just using the "isCompleted" field in order to avoid having to remove some "results" (or something) field later
    }
}, {
    $addFields: {
        "isCompleted": { $arrayElemAt: [ "$isCompleted", 0 ] } // take the first matched document only
    }
}, {
    $addFields: { // add the required fields to the top level structure
        "isCompleted": "$isCompleted.isCompleted", // here, we set the "isCompleted" field to its real value
        "serialNo": "$isCompleted.serialNo",
        "batchNo": "$isCompleted.batchNo"
    }
}])