如何在mongodb聚合输出中包含不匹配的文档?

如何在mongodb聚合输出中包含不匹配的文档?,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我在下面写了聚合,它是在集合中展开一个数组,然后检查每个展开的文档是否与给定对象id数组中的任何元素匹配。投影时,生成的集合将通过条件对其进行进一步过滤 db.collectionName.aggregate([ { $unwind: { path: "$field5", preserveNullAndEmptyArrays: true } }, { $match: { field5: { $in:

我在下面写了聚合,它是在集合中展开一个数组,然后检查每个展开的文档是否与给定对象id数组中的任何元素匹配。投影时,生成的集合将通过条件对其进行进一步过滤

  db.collectionName.aggregate([
    { $unwind: { 
          path: "$field5", 
          preserveNullAndEmptyArrays: true 
        } 
    },
    { $match: {  field5: { $in: 

       [
          ObjectId("id1"),
          ObjectId("id2"),
          ObjectId("id3")
      ]

        } } },
    { $project: { 
        _id: 0,
        field0: "$field0",
        field1: "$field1",
        field2: "$field2",
        customField: { 
            $or:[{
                  $and: [ 
                      { /*...some  condition*/ } ,  
                      { /*...some condition*/  }   
                    ],
                },
                { 
                    $and: [ 
                      { /*...some  condition*/ } , 
                      {  /*...some  condition*/ }   
                    ]
              }]
           }
       } 
     }
  ])     
这正如预期的那样有效

结果

/* 1 */
{
    "field0" : "processing",
    "field5" : ObjectId("id1"),
    "field1" : "val",
    "field2" : "val",
    "customField" : false
}

/* 2 */
{
    "field0" : "processing",
    "field5" : ObjectId("id2"),
    "field1" : "val",
    "field2" : "val",
    "customField" : false
}
如果我理解正确,$match stage会删除不匹配的id(比如id3)。如何通过创建一个包含所有字段的单独文档来在最终输出中获得它

期待什么

/* 1 */
{
    "field0" : "processing",
    "field5" : ObjectId("id1"),
    "field1" : "val",
    "field2" : "val",
    "customField" : false
}

/* 2 */
{
    "field0" : "processing",
    "field5" : ObjectId("id2"),
    "field1" : "val",
    "field2" : "val",
    "customField" : true
}


/* 3 */
/* Note that id3 is unmatched (excluded by $match in result) */
{
    "field0" : "processing",
    "field5" : ObjectId("id3"),
    "field1" : "val",
    "field2" : "val",
    "customField" : true
}

有没有办法做到这一点

是的,你可以做到,但这有点棘手

$facet
将有助于实现这一目标

db.collection.aggregate([
  {
  $facet:{
    "matched":[
      { 
        $unwind:{ 
          path: "$field5", 
          preserveNullAndEmptyArrays: true 
        } 
      },
      { 
        $match:{  
          field5: {
            $in:
             [
                ObjectId("id1"),
                ObjectId("id2"),
                ObjectId("id3")
             ]
          } 
        } 
      },
      { 
        $project: { 
          _id: 0,
          field0: "$field0",
          field1: "$field1",
          field2: "$field2",
          customField: { 
              $or:[{
                    $and: [ 
                        { /*...some  condition*/ } ,  
                        { /*...some condition*/  }   
                      ],
                  },
                  { 
                      $and: [ 
                        { /*...some  condition*/ } , 
                        {  /*...some  condition*/ }   
                      ]
                }]
             }
         } 
       }
    ],
    "unmatched":[
    { 
      $unwind:{ 
        path: "$field5", 
        preserveNullAndEmptyArrays: true 
      } 
    },
    { 
      $match:{  
        field5: {
          $nin:
           [
              ObjectId("id1"),
              ObjectId("id2"),
              ObjectId("id3")
           ]
        } 
      } 
    },
    { 
      $project: { 
        _id: 0,
        field0: "$field0",
        field1: "$field1",
        field2: "$field2",
        customField: { 
            $or:[{
                  $and: [ 
                      { /*...some  condition*/ } ,  
                      { /*...some condition*/  }   
                    ],
                },
                { 
                    $and: [ 
                      { /*...some  condition*/ } , 
                      {  /*...some  condition*/ }   
                    ]
              }]
           }
       } 
     }
    ]
  }
  },
  {
    $project:{
      "all":{
        $concatArrays:[
          "$matched",
          "$unmatched"
        ]
      }
    }
  },
  {
    $unwind:"$all"
  },
  {
    $replaceRoot:{
      newRoot:"$all"
    }
  }
]).pretty()
希望这将有助于您的用例

此外,您还可以根据需要更新这两个方面(“匹配”和“未匹配”)


您可以找到有关$facet的更多信息是的,您可以实现这一点,但这有点棘手

$facet
将有助于实现这一目标

db.collection.aggregate([
  {
  $facet:{
    "matched":[
      { 
        $unwind:{ 
          path: "$field5", 
          preserveNullAndEmptyArrays: true 
        } 
      },
      { 
        $match:{  
          field5: {
            $in:
             [
                ObjectId("id1"),
                ObjectId("id2"),
                ObjectId("id3")
             ]
          } 
        } 
      },
      { 
        $project: { 
          _id: 0,
          field0: "$field0",
          field1: "$field1",
          field2: "$field2",
          customField: { 
              $or:[{
                    $and: [ 
                        { /*...some  condition*/ } ,  
                        { /*...some condition*/  }   
                      ],
                  },
                  { 
                      $and: [ 
                        { /*...some  condition*/ } , 
                        {  /*...some  condition*/ }   
                      ]
                }]
             }
         } 
       }
    ],
    "unmatched":[
    { 
      $unwind:{ 
        path: "$field5", 
        preserveNullAndEmptyArrays: true 
      } 
    },
    { 
      $match:{  
        field5: {
          $nin:
           [
              ObjectId("id1"),
              ObjectId("id2"),
              ObjectId("id3")
           ]
        } 
      } 
    },
    { 
      $project: { 
        _id: 0,
        field0: "$field0",
        field1: "$field1",
        field2: "$field2",
        customField: { 
            $or:[{
                  $and: [ 
                      { /*...some  condition*/ } ,  
                      { /*...some condition*/  }   
                    ],
                },
                { 
                    $and: [ 
                      { /*...some  condition*/ } , 
                      {  /*...some  condition*/ }   
                    ]
              }]
           }
       } 
     }
    ]
  }
  },
  {
    $project:{
      "all":{
        $concatArrays:[
          "$matched",
          "$unmatched"
        ]
      }
    }
  },
  {
    $unwind:"$all"
  },
  {
    $replaceRoot:{
      newRoot:"$all"
    }
  }
]).pretty()
希望这将有助于您的用例

此外,您还可以根据需要更新这两个方面(“匹配”和“未匹配”)


您可以找到有关$facet的更多信息

该查询是否真的排除了第三个文档?根据
$match
的规定,它也应该包括它!!无论如何,您是否需要在同一输出中使用匹配和不匹配的文档?如果是-那么这两种类型之间的区别是什么(类似于任何表示匹配文档为true的字段和表示未匹配文档为false的字段)?如果没有这样的事情,那么做
$match
是没有用的,如果是这样的话,你实际上发布了你的原始需求,以便有人可以在这方面帮助你..@whoami谢谢你的回复。抱歉,我可能也应该解释一下这个用例。collectionName保留要匹配的id临时条目(在field5中,它是一个数组)。$match阶段将展开文档与传递给它的数组进行比较,以查找匹配项。这就是我没有看到id3的地方,也不确定它是否正确。我想保留无与伦比的价值,并将其保留在某个地方。不匹配的值也不会根据$project中的条件进行检查,因此不会进一步筛选,并应包含在最终结果中。因此,您只需在输出中保留不匹配的文档,同时还需要对匹配的文档执行更多操作?因此,您是否希望在结束时为每个单独的文档返回多个文档(正如您正在执行的
$unwind
),如果是,则有必要展开,否则就不需要(因此,您所做的是将字段5上的单个文档拆分为多个文档,并将它们分类为匹配与不匹配,一天结束时,它是具有不同字段5的同一个文档)?? 无论如何,在您给定的示例文档和查询中,我认为您应该使用
ObjectId(“id3”)
获取文档,但不确定您为什么不获取it@whoami,谢谢你的回复。现在,我将匹配的结果和临时条目(field5数组)进行比较,并只向其中添加缺少或不匹配的项。这似乎是一个肮脏的黑客行为,但正在发挥作用。这个查询真的排除了第三个文档吗?根据
$match
的规定,它也应该包括它!!无论如何,您是否需要在同一输出中使用匹配和不匹配的文档?如果是-那么这两种类型之间的区别是什么(类似于任何表示匹配文档为true的字段和表示未匹配文档为false的字段)?如果没有这样的事情,那么做
$match
是没有用的,如果是这样的话,你实际上发布了你的原始需求,以便有人可以在这方面帮助你..@whoami谢谢你的回复。抱歉,我可能也应该解释一下这个用例。collectionName保留要匹配的id临时条目(在field5中,它是一个数组)。$match阶段将展开文档与传递给它的数组进行比较,以查找匹配项。这就是我没有看到id3的地方,也不确定它是否正确。我想保留无与伦比的价值,并将其保留在某个地方。不匹配的值也不会根据$project中的条件进行检查,因此不会进一步筛选,并应包含在最终结果中。因此,您只需在输出中保留不匹配的文档,同时还需要对匹配的文档执行更多操作?因此,您是否希望在结束时为每个单独的文档返回多个文档(正如您正在执行的
$unwind
),如果是,则有必要展开,否则就不需要(因此,您所做的是将字段5上的单个文档拆分为多个文档,并将它们分类为匹配与不匹配,一天结束时,它是具有不同字段5的同一个文档)?? 无论如何,在您给定的示例文档和查询中,我认为您应该使用
ObjectId(“id3”)
获取文档,但不确定您为什么不获取it@whoami,谢谢你的回复。现在,我将匹配的结果和临时条目(field5数组)进行比较,并只向其中添加缺少或不匹配的项。这似乎是一个肮脏的黑客,但工作。$facets看起来很有趣。我一定要试试。到目前为止,我正在将匹配的结果与临时条目(field5数组)进行比较,并只向其中添加缺少或不匹配的项。谢谢。关于
$facet
还有一件事是它同时运行,即;facet中的所有阶段将同时运行。$facets看起来很有趣。我一定要试试。到目前为止,我正在将匹配的结果与临时条目(field5数组)进行比较,并只向其中添加缺少或不匹配的项。谢谢。关于
$facet
还有一件事是它同时运行,即;方面中的所有阶段将同时运行。