文档简单如下:
[
{'id': '1', 'type': 'a', 'startedAt': '2017-06-11'},
{'id': '2', 'type': 'b', 'startedAt': ''},
{'id': '3', 'type': 'b', 'startedAt': '2017-06-11'}
]
预期的汇总结果:
[
{'type': 'a', 'started': true, 'count': 1},
{'type': 'b', 'started': true, 'count': 1},
{'type': 'b', 'started': false, 'count': 1}
]
如何使用mongodb nodejs驱动程序获得上述结果?
我尝试过如下,但它没有工作('已开始'始终为空):
db.collection('docs').group(
{'type': '$type', 'started': {
$cond: [{$eq: ['$startedAt': '']}, false, true ]
}},
{},
{'total': 0},
'function(curr, result) {result.total++}'
)
答案 0 :(得分:2)
你在这里使用.aggregate()
而不是.group()
,这完全是另一个功能:
db.collection('docs').aggregate([
{ "$group": {
"_id": {
"type": "$type",
"started": {
"$gt": [ "$startedAt", "" ]
}
},
"count": { "$sum": 1 }
}}
],function(err, results) {
console.log(results);
})
$gt
运算符在满足条件时返回true
。在这种情况下,字符串中的任何内容都大于"大于"一个空字符串。
如果该字段实际上是"根本不存在"然后我们可以适应$ifNull
。如果属性实际上不存在,则给出默认值,否则计算为null
。
db.collection('docs').aggregate([
{ "$group": {
"_id": {
"type": "$type",
"started": {
"$gt": [ { "$ifNull": [ "$startedAt", ""] }, "" ]
}
},
"count": { "$sum": 1 }
}}
],function(err, results) {
console.log(results);
})
这会产生:
{ "_id" : { "type" : "b", "started" : true }, "count" : 1 }
{ "_id" : { "type" : "b", "started" : false }, "count" : 1 }
{ "_id" : { "type" : "a", "started" : true }, "count" : 1 }
您可以选择$project
之后将结果中的字段更改为_id
,但实际上您不应该这样做,因为这意味着您可以轻松访问无论如何都要有价值。
结果只是.map()
:
console.log(
results.map(function(r) {
return { type: r._id.type, started: r._id.started, count: r.count }
})
);
但$project
:
db.collection('docs').aggregate([
{ "$group": {
"_id": {
"type": "$type",
"started": {
"$gt": [ { "$ifNull": [ "$startedAt", ""] }, "" ]
}
},
"tcount": { "$sum": 1 }
}},
{ "$project": {
"_id": 0,
"type": "$_id.type",
"started": "$_id.started",
"count": "$tcount"
}}
],function(err, results) {
console.log(results);
})
产生您想要的格式
{ "type" : "b", "started" : true, "count" : 1 }
{ "type" : "b", "started" : false, "count" : 1 }
{ "type" : "a", "started" : true, "count" : 1 }
供参考,.group()
的正确用法是:
db.collection('docs').group(
function(doc) {
return {
"type": doc.type,
"started": (
(doc.hasOwnProperty('startedAt') ? doc.startedAt : "") > ""
)
}
},
[],
{ "count": 0 },
function(curr,result) {
result.count += 1
},
function(err,results) {
console.log(results);
}
);
返回:
[
{ "type" : "a", "started" : true, "count" : 1 },
{ "type" : "b", "started" : false, "count" : 1 },
{ "type" : "b", "started" : true, "count" : 1 }
]
但你真的不应该使用,因为.group()
依赖于JavaScript评估,其运行速度比.aggregate()