如何在mongo聚合中使用$ in或$ nin $ group $ cond [英] How to use $in or $nin in mongo aggregation $group $cond
问题描述
我想通过在属性上设置$ or来用$ cond实现$ sum:
db.collectionName.aggregate(
{
"$group": {
"_id":'$created_at',
"count": {"$sum": 1},
"count_failure": {
"$sum": {
"$cond": [
{
"$id":
{ "$in": [ 0,100,101,102,103,104,105 ] }
},
1,
0
]
}
}
}
}
)
但是错误提示:Invalid operator "$id"
语法有什么问题?还是我写错了查询.
目前,我正在通过以下方式实现这一目标:
db.collectionName.aggregate(
{
"$group": {
"_id":'$created_at',
"count": {"$sum": 1},
"count_failure": {
"$sum": {
"$cond": [
{
"$or":[
{ "$eq": [ "$id", 0 ] },
{ "$eq": [ "$id", 100 ]},
{ "$eq": [ "$id", 101 ]},
{ "$eq": [ "$id", 102 ]},
{ "$eq": [ "$id", 103 ]},
{ "$eq": [ "$id", 104 ]},
{ "$eq": [ "$id", 105 ]}
]
},
1,
0
]
}
}
}
}
)
$setIsSubset
上的比较短选项,而不是您正在使用的$or
条件,尽管基本上可以执行您正在做的事情.
$setIsSubset
的唯一问题是每个参数都是一个数组,因此您需要将单个元素转换为单个元素数组.使用 $map
:
db.collectionName.aggregate([
{ "$group": {
"_id": "$createdAt",
"count": { "$sum": 1 },
"count_failure": {
"$sum": {
"$cond": [
{ "$setIsSubset": [
{ "$map": {
"input": ["A"],
"as": "el",
"in": "$id"
}},
[ 0,100,101,102,103,104,105 ],
]},
1,
0
]
}
}
}}
])
或者,如果愿意,可以使用 $anyElementTrue
:
db.collectionName.aggregate([
{ "$group": {
"_id": "$createdAt",
"count": { "$sum": 1 },
"count_failure": {
"$sum": {
"$cond": [
{ "$anyElementTrue": { "$map": {
"input": [ 0,100,101,102,103,104,105 ],
"as": "el",
"in": { "$eq": [ "$$el", "$id" ] }
}}},
1,
0
]
}
}
}}
])
$map
只是遍历参数以匹配单数,而不是将单数强制为数组.
当然,由于这两种形式本质上都是为 这实际上取决于您的外观,但是仅作为提供的参数,使用 即 然后在管道定义中使用重新映射的数组内容: 无论您以何种方式看待它,请记住,它们全都是数据结构,并且具有基本的操作过程.不仅在管道处理内部,而且在管道构建本身中. I want to achieve $sum with $cond by having $or on property: But error says: What's wrong with syntax? Or I am writing query wrongly. Currently I am achieving this by:
The comparison on The only catch with Or if you prefer, then match the array of arguments against the singular value instead, with Where the And of course since either form is essentially supplying It really depends on how you look at it, but simply as supplied arguments then you don't really gain anything over the original form with i.e And then just using the re-mapped array content in the pipeline definition: Whatever way you look at it, remember it's all just data structures and you have basic processes for manipulating. Both inside the pipeline processing and also in the pipeline construction itself. 这篇关于如何在mongo聚合中使用$ in或$ nin $ group $ cond的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!$cond
提供true/false
,因此您可以使用 db.collectionName.aggregate([
{ "$group": {
"_id": "$createdAt",
"count": { "$sum": 1 },
"count_failure": {
"$sum": {
"$cond": [
{ "$not": [{ "$anyElementTrue": { "$map": {
"input": [ 0,100,101,102,103,104,105 ],
"as": "el",
"in": { "$eq": [ "$$el", "$id" ] }
}}}]},
1,
0
]
}
}
}}
])
$or
并不会真正获得超过原始形式的任何东西.看起来可能更简洁,更容易键入,但是通常我不会直接在聚合管道中键入"这种逻辑,而是首先基于简单列表生成结构的那部分:>
var failList = [ 0,100,101,102,103,104,105 ];
var orCondition = failList.map(function(el) {
return { "$eq": [ "$id", el ] }
})
{ "$group": {
"_id": "$createdAt",
"count": { "$sum": 1 },
"count_failure": {
"$sum": {
"$cond": [
{ "$or": orCondition },
1,
0
]
}
}
}}
])
db.collectionName.aggregate(
{
"$group": {
"_id":'$created_at',
"count": {"$sum": 1},
"count_failure": {
"$sum": {
"$cond": [
{
"$id":
{ "$in": [ 0,100,101,102,103,104,105 ] }
},
1,
0
]
}
}
}
}
)
Invalid operator "$id"
db.collectionName.aggregate(
{
"$group": {
"_id":'$created_at',
"count": {"$sum": 1},
"count_failure": {
"$sum": {
"$cond": [
{
"$or":[
{ "$eq": [ "$id", 0 ] },
{ "$eq": [ "$id", 100 ]},
{ "$eq": [ "$id", 101 ]},
{ "$eq": [ "$id", 102 ]},
{ "$eq": [ "$id", 103 ]},
{ "$eq": [ "$id", 104 ]},
{ "$eq": [ "$id", 105 ]}
]
},
1,
0
]
}
}
}
}
)
$setIsSubset
is a shorter option than the $or
condition you are using, though it's still basically valid to do what you are doing.$setIsSubset
is that each argument is an array so you need to convert the single element as a single element array. This is easy enough using $map
:db.collectionName.aggregate([
{ "$group": {
"_id": "$createdAt",
"count": { "$sum": 1 },
"count_failure": {
"$sum": {
"$cond": [
{ "$setIsSubset": [
{ "$map": {
"input": ["A"],
"as": "el",
"in": "$id"
}},
[ 0,100,101,102,103,104,105 ],
]},
1,
0
]
}
}
}}
])
$anyElementTrue
: db.collectionName.aggregate([
{ "$group": {
"_id": "$createdAt",
"count": { "$sum": 1 },
"count_failure": {
"$sum": {
"$cond": [
{ "$anyElementTrue": { "$map": {
"input": [ 0,100,101,102,103,104,105 ],
"as": "el",
"in": { "$eq": [ "$$el", "$id" ] }
}}},
1,
0
]
}
}
}}
])
$map
is rather traversing the arguments to match to the singular rather than forcing the singular into an array.true/false
to the $cond
then you can just reverse the logic with $not
where required:db.collectionName.aggregate([
{ "$group": {
"_id": "$createdAt",
"count": { "$sum": 1 },
"count_failure": {
"$sum": {
"$cond": [
{ "$not": [{ "$anyElementTrue": { "$map": {
"input": [ 0,100,101,102,103,104,105 ],
"as": "el",
"in": { "$eq": [ "$$el", "$id" ] }
}}}]},
1,
0
]
}
}
}}
])
$or
. It might look a little cleaner and "easier to type", but typically I would not be "typing" such logic into the aggregation pipeline directly, but rather generating that part of the structure based on a plain list in the first place:var failList = [ 0,100,101,102,103,104,105 ];
var orCondition = failList.map(function(el) {
return { "$eq": [ "$id", el ] }
})
{ "$group": {
"_id": "$createdAt",
"count": { "$sum": 1 },
"count_failure": {
"$sum": {
"$cond": [
{ "$or": orCondition },
1,
0
]
}
}
}}
])