MongoDB聚合-匹配数组中的if值

MongoDB聚合-匹配数组中的if值,mongodb,aggregation-framework,Mongodb,Aggregation Framework,我有一个集合,我正在对它进行聚合,我基本上已经把它归结为 {array:[1,2,3], value: 1}, {array:[1,2,3], value: 4} 如何执行聚合匹配以检查值是否在数组中?我试着使用{$match:{“数组:{$in:[“$value”]}}}但是没有找到任何东西 我希望输出(如果使用上述示例)为: 更有效的方法包括使用操作符的单个管道,如下所示: db.collection.aggregate([ { "$redact": {

我有一个集合,我正在对它进行聚合,我基本上已经把它归结为

{array:[1,2,3], value: 1},
{array:[1,2,3], value: 4}
如何执行聚合匹配以检查值是否在数组中?我试着使用
{$match:{“数组:{$in:[“$value”]}}}
但是没有找到任何东西

我希望输出(如果使用上述示例)为:


更有效的方法包括使用操作符的单个管道,如下所示:

db.collection.aggregate([
    { 
        "$redact": {
            "$cond": [
                { 
                    "$setIsSubset": [ 
                        ["$value"],
                        "$array"  
                    ] 
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

不支持<强> >/St>(版本< 2.6)的MyGoDB的早期版本,然后考虑使用<强> <强>运算符的聚合管道:

db.collection.aggregate([
    { "$unwind": "$array" },
    {
        "$project": {
            "isInArray": {
                "$cond": [
                    { "$eq": [ "$array", "$value" ] },
                    1,
                    0
                ]
            },
            "value": 1,
            "array": 1
        }
    },
    { "$sort": { "isInArray": -1 } },
    {
        "$group": {
            "_id": {
                "_id": "$_id",
                "value": "$value"
            },
            "array": { "$push": "$array" },
            "isInArray": { "$first": "$isInArray" }
        }
    },
    { "$match": { "isInArray": 1 } },
    { "$project": { "value": "$_id.value", "array": 1, "_id": 0 } }
])

根据@chridam的回答,有一点变化:

db.test.aggregate([
    { "$unwind": "$array" },
    { "$group": {
                  _id: { "_id": "$_id", "value": "$value" },
                  array: { $push: "$array" },
                  mcount: { $sum: {$cond: [{$eq: ["$value","$array"]},1,0]}}
                }
    },
    { $match: {mcount: {$gt: 0}}},
    { "$project": { "value": "$_id.value", "array": 1, "_id": 0 }}
])
想法是
$unwind
$group
返回数组,在
mcount
中计算与该值匹配的项数。之后,在
mcount>0
上执行一个简单的
$match
将过滤掉不需要的文档。

如上所述,在不需要继续聚合逻辑的情况下,这是一个很好的选择离子管道

但是,如果使用,则使用将“值”转换为数组并使用进行比较。这是最快的方法,因为您不需要使用以下方法复制文档:

db.collection.aggregate([
{“$redact”:{
“$cond”:{
“如果”:{“$setIsSubset”:[
{“$map”:{
“输入”:{“$literal”:[“A”]},
“as”:“a”,
“in”:“$value”
}},
“$array”
]},
“然后”:“$$KEEP”,
“else”:“$$PRUNE”
}
}}
])
$redact
管道运算符允许处理其中的逻辑条件,并使用特殊操作“保留”逻辑条件为真的文档或“删除”条件为假的文档

这使得它可以像处理后续的、但在单个管道阶段中工作,这样效率更高


考虑到这些是本机编码的运算符,而不是JavaScript,那么这可能是执行匹配的“最快”方法。因此,如果您使用的是MongoDB 2.6或更高版本,那么您应该使用这种方法来比较文档中的这些元素。

尝试将$eq和$setIntersection结合使用

{$group :{
  _id: "$id",
  yourName :  { $sum:
  { $cond :[
       {$and : [
          {$eq:[{$setIntersection : ["$someArrayField", ["$value"]]  },["$value"]]}
         ]
      },1,0]
  }
}
}回答有点晚,但这提出了另一种解决方案:

通过分别使用addFields和match,这比编校提供了更多的灵活性。您可以公开多个字段,然后根据结果一起使用其他匹配逻辑

db.applications.aggregate([
    {$addFields: {"containsValueInArray": {$cond:[{$setIsSubset: [["valueToMatch"], "$arrayToMatchIn"]},true,false]}}},
    {$match: {"containsValueInArray":true}}
]);

您可以在3.6版本的常规查询中使用聚合表达式

db.collection_name.find({"$expr": {"$in": ["$value", "$array"]}})
使用聚合:

您可以在当前的
3.6
版本中使用
$match+$expr

db.collection_name.aggregate({"$match": {"$expr": {"$in": ["$value", "$array"]}}})
db.collection_name.aggregate({
  "$redact": {
    "$cond": [
      {
        "$in": [
          "$value",
          "$array"
        ]
      },
      "$$KEEP",
      "$$PRUNE"
    ]
  }
})
您可以在
3.4
版本中尝试
$redact+$in
表达式

db.collection_name.aggregate({"$match": {"$expr": {"$in": ["$value", "$array"]}}})
db.collection_name.aggregate({
  "$redact": {
    "$cond": [
      {
        "$in": [
          "$value",
          "$array"
        ]
      },
      "$$KEEP",
      "$$PRUNE"
    ]
  }
})

我更喜欢不分组,因为从v.3.2开始有一种简单的方法

...aggregate([
      {
        $addFields: {
          arrayFilter: {
            $filter: {
              input: '$array',
              as: 'item',
              cond: ['$$item', '$value']
            }
          }
        }
      },
      {
        $unwind: '$arrayFilter'
      },
      {
        $project: {
          arrayFilter: 0
        }
      }
    ]);
  • 添加临时筛选器字段
  • $在结果数组上展开(删除带有空数组的管道结果)
  • (可选)通过项目从结果中删除筛选字段

  • 您可以使用简单的$project&$match来完成

    db.test.aggregate([{
    $project: {
                  arrayValue: 1,
                  value: 1,
                  "has_same_value" : { $in: ["$value", "$arrayValue"] }
              }
    },
    {
       $match: {has_same_value: true}
    },
    {
      $project: {has_same_value: 0}
    }])
    

    我还没有尝试过,但我认为您可能想要
    $elemMatch
    (请参阅)与其说
    $in
    ,不如说你想测试一个值是否在数组中,而不是数组是否在值中!你真的需要回来看看这个问题,因为任何建议
    $unwind
    的人都给了你一个可能在代码中实现的最差性能答案。提交的备选方案有很多umbs升级为$redact。我不知道这一个,它正是我所需要的:在每个文档中查找数组中的特定值。谢谢!这并没有提供问题的答案。一旦您有足够的资源,您将能够;相反,.-以下是在字符串中使用名称数组时使用$Match和$的基本示例