Node.js 使用nodejs驱动程序进行聚合-根据字段是否为空进行分组
这些文档很简单,如下所示:Node.js 使用nodejs驱动程序进行聚合-根据字段是否为空进行分组,node.js,mongodb,aggregation-framework,Node.js,Mongodb,Aggregation Framework,这些文档很简单,如下所示: [ {'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', 's
[
{'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驱动程序获得上述结果
我尝试了以下方法,但没有成功('started'始终为空):
您可以在此处使用,也可以不使用,这是一个完全不同的函数:
db.collection('docs').aggregate([
{ "$group": {
"_id": {
"type": "$type",
"started": {
"$gt": [ "$startedAt", "" ]
}
},
"count": { "$sum": 1 }
}}
],function(err, results) {
console.log(results);
})
当条件满足时,操作员返回true
。在这种情况下,字符串中的任何内容都“大于”空字符串
如果这个领域实际上“根本不存在”,那么我们可以适应它。如果该属性实际上不存在,或其计算结果为null
,则会提供默认值have
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 }
您可以选择在以后更改结果中\u id
内的字段,但确实不应该这样做,因为这意味着额外的传递结果,而您仍然可以轻松访问这些值
因此,就结果而言:
console.log(
results.map(function(r) {
return { type: r._id.type, started: r._id.started, count: r.count }
})
);
但是:
产生你想要的格式
{ "type" : "b", "started" : true, "count" : 1 }
{ "type" : "b", "started" : false, "count" : 1 }
{ "type" : "a", "started" : true, "count" : 1 }
作为参考,正确的用法是:
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 }
]
但您确实不应该使用它,因为它依赖于JavaScript计算,而JavaScript计算的运行速度比您在此处使用的要慢得多,这是一个完全不同的函数:
db.collection('docs').aggregate([
{ "$group": {
"_id": {
"type": "$type",
"started": {
"$gt": [ "$startedAt", "" ]
}
},
"count": { "$sum": 1 }
}}
],function(err, results) {
console.log(results);
})
当条件满足时,操作员返回true
。在这种情况下,字符串中的任何内容都“大于”空字符串
如果这个领域实际上“根本不存在”,那么我们可以适应它。如果该属性实际上不存在,或其计算结果为null
,则会提供默认值have
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 }
您可以选择在以后更改结果中\u id
内的字段,但确实不应该这样做,因为这意味着额外的传递结果,而您仍然可以轻松访问这些值
因此,就结果而言:
console.log(
results.map(function(r) {
return { type: r._id.type, started: r._id.started, count: r.count }
})
);
但是:
产生你想要的格式
{ "type" : "b", "started" : true, "count" : 1 }
{ "type" : "b", "started" : false, "count" : 1 }
{ "type" : "a", "started" : true, "count" : 1 }
作为参考,正确的用法是:
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 }
]
但您真的不应该使用它,因为它依赖于JavaScript评估,而JavaScript评估的运行速度比您可以使用的速度慢得多这个答案是全面的,更不用说有效了。我将坚持使用.aggregate+.map,而不使用$project或.group@尼尔·伦,非常感谢!这个答案很全面,更不用说有效了。我将坚持使用.aggregate+.map,而不使用$project或.group@尼尔·伦,非常感谢!