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和$的基本示例