Javascript 已跳过聚合函数中的计数0
这件事我已经坚持了好几天了。我正在尝试获取Javascript 已跳过聚合函数中的计数0,javascript,node.js,mongodb,mongodb-query,aggregation-framework,Javascript,Node.js,Mongodb,Mongodb Query,Aggregation Framework,这件事我已经坚持了好几天了。我正在尝试获取计数:0,其中给定时间段内没有文档。这是我目前正在使用的聚合函数: var getCount = function(timeBlock, start, end, cb) { Document.aggregate( { $match: { time: { $gte: new Date(start), $lt: new Date(end)
计数:0
,其中给定时间段内没有文档。这是我目前正在使用的聚合函数:
var getCount = function(timeBlock, start, end, cb) {
Document.aggregate(
{
$match: {
time: {
$gte: new Date(start),
$lt: new Date(end)
}
}
},
{
$project: {
time: 1,
delta: { $subtract: [
new Date(end),
'$time'
]}
}
},
{
$project: {
time: 1,
delta: { $subtract: [
"$delta",
{ $mod: [
"$delta",
timeBlock
]}
]}
}
},
{
$group: {
_id: { $subtract: [
end,
"$delta"
]},
count: { $sum: 1 }
}
},
{
$project: {
time: "$_id",
count: 1,
_id: 0
}
},
{
$sort: {
time: 1
}
}, function(err, results) {
if (err) {
cb(err)
} else {
cb(null, results)
}
})
}
我尝试使用
$cond
,但运气不佳这是我目前所做的黑客修复:
var getCount = function(timeBlock, start, end, cb) {
Document.aggregate(
{
$match: {
time: {
$gte: new Date(start),
$lt: new Date(end)
}
}
},
{
$project: {
time: 1,
delta: { $subtract: [
new Date(end),
'$time'
]}
}
},
{
$project: {
time: 1,
delta: { $subtract: [
"$delta",
{ $mod: [
"$delta",
timeBlock
]}
]}
}
},
{
$group: {
_id: { $subtract: [
end,
"$delta"
]},
count: { $sum: 1 }
}
},
{
$project: {
time: "$_id",
count: 1,
_id: 0
}
},
{
$sort: {
time: 1
}
}, function(err, results) {
if (err) {
cb(err)
} else {
// really hacky way
var numOfTimeBlocks = ( end - start ) / timeBlock
// in case there is no 0s in the given period of time there is no need
// to iterate through all of the results
if ( results.length === numOfTimeBlocks ) {
cb(results);
} else {
var time = start;
var details = [];
var times = results.map(function(item) {
return item.time;
});
for( var i = 0; i < numOfTimeBlocks; i++) {
time += timeBlock;
var idx = times.indexOf(time);
if (idx > -1) {
details.push(results[idx]);
} else {
var documentCount = { count: 0, time: time };
details.push(documentCount);
}
}
cb(details);
}
}
})
}
var getCount=函数(时间块、开始、结束、cb){
Document.aggregate(
{
$match:{
时间:{
$gte:新日期(开始),
$lt:新日期(结束)
}
}
},
{
$项目:{
时间:1,,
增量:{$subtract:[
新日期(完),
“$time”
]}
}
},
{
$项目:{
时间:1,,
增量:{$subtract:[
“$delta”,
{$mod:[
“$delta”,
计时器
]}
]}
}
},
{
$group:{
_id:{$subtract:[
完,,
“$delta”
]},
计数:{$sum:1}
}
},
{
$项目:{
时间:“$\u id”,
计数:1,
_身份证号码:0
}
},
{
$sort:{
时间:1
}
},函数(错误,结果){
如果(错误){
cb(err)
}否则{
//真讨厌
var numOfTimeBlocks=(结束-开始)/timeBlock
//如果在给定的时间段内没有0,则不需要
//遍历所有结果
if(results.length==numOfTimeBlocks){
cb(结果);
}否则{
var时间=开始;
var详细信息=[];
变量时间=results.map(函数(项){
返回项目时间;
});
对于(var i=0;i-1){
推送(结果[idx]);
}否则{
var documentCount={count:0,time:time};
详情。推送(文档计数);
}
}
cb(详情);
}
}
})
}
我还考虑过对每个时间块执行一次查询,这会给出相同的结果,但我认为这是低效的,因为您要查询数据库N次。分组阶段是根据您给定的_id进行分组,并计算前一阶段中最终在组中的文档数来生成文档。因此,计数为零将是从属于该组的0个输入文档创建文档的结果。从这个角度考虑,显然聚合管道无法为您做到这一点。它不知道所有“缺失”的时间段是什么,也不能凭空发明合适的文档。如果你需要空时段的显式计数为0,那么重新应用你关于缺失时段的额外知识以在最后完成图片似乎是一个合理的解决方案(而不是“哈克”)。尽管已经说过,在这里最好的做法是“合并”你的结果后处理,而不是期望“关键点”不会出现或发出带有显式键的多个查询,这些键可能不会聚合结果并组合它们 还没有提到的是你是如何做到这一点的,所以我将给你一种MongoDB“思考”的方式来收集你的结果 作为快速免责声明,您可以使用大致相同的方法,使用mapReduce为每个间隔“播种”空键,甚至可能更改数据,以便在每个可能的块中始终存在空值。这些方法看起来基本上是“黑客式”的,在mapReduce的例子中,无法提供最佳性能或多重结果 我的建议是,可以简化MongoDB大脑的收集结果。有一个简洁的小解决方案叫做,它被称为MongoDB的一种SQLLite。它支持一部分功能,因此非常适合使用MongoDB思维对结果进行“内存”操作:
var async = require('async'),
mongoose = require('mongoose'),
DataStore = require('nedb'),
Schema = mongoose.Schema;
var documentSchema = new Schema({
time: { type: Date, default: Date.now }
});
var Document = mongoose.model( "Document", documentSchema );
mongoose.connect('mongodb://localhost/test');
var getCount = function(timeBlock, start, end, callback) {
async.waterfall(
[
// Fill a blank series
function(callback) {
var db = new DataStore();
var current = start;
async.whilst(
function() { return current < end },
function(callback) {
var delta = end - current;
db.insert({ "_id": end - delta, "count": 0 },function(err,doc) {
//console.log( doc );
current += timeBlock;
callback(err);
});
},
function(err) {
callback(err,db);
}
);
},
// Get data and update
function(db,callback) {
var cursor = Document.collection.aggregate(
[
// Match documents
{ "$match": {
"time": {
"$gte": new Date(start),
"$lt": new Date(end)
}
}},
// Group. 1 step and less hacky
{ "$group": {
"_id": {
"$let": {
"vars": {
"delta": {
"$subtract": [
{ "$subtract": [ new Date(end), "$time" ] },
{ "$mod": [
{ "$subtract": [ new Date(end), "$time" ] },
timeBlock
]}
]
}
},
"in": { "$subtract": [ end, "$$delta" ] }
}
},
"count": { "$sum": 1 }
}}
],
{ "cursor": { "batchSize": 100 } }
);
cursor.on("data",function(item) {
cursor.pause();
console.log( "called" );
db.update(
{ "_id": item._id },
{ "$inc": { "count": item.count } },
{ "upsert": true },
function(err) {
cursor.resume();
}
);
});
cursor.on("end",function() {
console.log( "done" );
db.find({},function(err,result) {
callback(err,result);
});
});
}
],
function(err,result) {
callback(err,result);
}
);
}
mongoose.connection.on("open", function(err,conn) {
getCount(
1000 * 60 * 60, // each hour
new Date("2014-07-01").valueOf(), // start
new Date("2014-07-02").valueOf(), // end
function(err,result) {
if (err) throw err;
console.log( result );
}
);
});
var async=require('async'),
mongoose=require('mongoose'),
DataStore=require('nedb'),
Schema=mongoose.Schema;
var documentSchema=新模式({
时间:{type:Date,默认值:Date.now}
});
var Document=mongoose.model(“Document”,documentSchema);
猫鼬mongodb://localhost/test');
var getCount=函数(时间块、开始、结束、回调){
异步瀑布(
[
//填空
函数(回调){
var db=新数据存储();
无功电流=启动;
异步的(
函数(){返回当前值