Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MongoDB按非完整时钟小时进行聚合_Mongodb_Aggregation Framework - Fatal编程技术网

MongoDB按非完整时钟小时进行聚合

MongoDB按非完整时钟小时进行聚合,mongodb,aggregation-framework,Mongodb,Aggregation Framework,首先,我必须说我在mongoDB方面没有丰富的经验,可能由于这个原因,我无法解决以下问题。 问题是,我需要聚合记录,不是按完整的时钟小时数,而是按第一条记录到达时开始的小时数,以及距离前一个事件一小时的时间 例如: 时间 柜台 还没有记录 0 11:55 1. 11:58 1. 12:02 1. 12:05 1. 12:55 1. 12:56 2. 13:04 2. 因为这在MongoDB中不是一项简单的任务,所以最好在业务逻辑中完成。您想要实现的结果基本上是一种范围内的聚合形式。问题是,您的范

首先,我必须说我在mongoDB方面没有丰富的经验,可能由于这个原因,我无法解决以下问题。 问题是,我需要聚合记录,不是按完整的时钟小时数,而是按第一条记录到达时开始的小时数,以及距离前一个事件一小时的时间

例如:

时间 柜台 还没有记录 0 11:55 1. 11:58 1. 12:02 1. 12:05 1. 12:55 1. 12:56 2. 13:04 2.
因为这在MongoDB中不是一项简单的任务,所以最好在业务逻辑中完成。您想要实现的结果基本上是一种范围内的聚合形式。问题是,您的范围不是预定义的集合,而是动态的,并基于第一个条目+附加时间值进行计算。所以,基本上你有:
[firstTime->firstTime+60m]
[firstTime+60m+1s->firstTime+60m+60m]
。。。无限远。这是可行的,但需要对分组阶段或投影计算使用粗糙的动态表达式。对于您的用例来说,这两种方法似乎都不必要复杂

如果你真的想走这条路,你可以查看一些相关的场景


如果决定在业务逻辑中执行此操作,则根据数据集的大小,可以批处理数据,使其不超过可用内存,但只有在首次使用大小合适的未处理数据集计算聚合时,这才应该是一个问题。此外,在任何情况下,都应该缓存计算结果,因为它们不会改变(当然,上次打开的日期范围除外)。考虑到你这样做是为了统计,而且你没有性能限制,你绝对应该帮自己一个忙,用更易于维护的方式在代码中完成它。

你的示例数据仍然是无用的!移除所有不相关的东西。为满足所有要求,请提供2份以上的文件

无论如何,我会尽力的

将日期/时间值存储为字符串(或数字)是一种非常糟糕的设计。始终使用适当的
Date
对象

db.collection.aggregate([
   // convert string into proper `Date` object 
   { $set: { ts: { $dateFromString: { dateString: "event.dateTime", format: "%Y%m%d%H:%M:%S" } } } }
   { $sort: { ts: 1 } },
   // put documents into an array
   { $group: { _id: { date: "$event.date", organisationId: "$organisationId" }, data: { $push: "$$ROOT" } } },
   {
      $set: {
         data: {
            $reduce: {
               input: "$data",
               initialValue: [],
               in: {
                  $concatArrays: [
                     "$$value",
                     [
                        {
                           $cond: {
                              // compare timestamp with boundary of previous element  
                              if: { $gt: ["$$this.ts", { $last: "$$value.boundary" }] },
                              // new interval: increase bucket number and set new boudnary
                              then: {
                                 $mergeObjects: [
                                    "$$this", {
                                       bucket: { $add: [{ $ifNull: [{ $last: "$$value.bucket" }, 0] }, 1] },
                                       boundary: { $add: ["$$this.ts", 1000 * 60 * 60] }
                                    }
                                 ]
                              },
                              // same interval: append element   
                              else: { $mergeObjects: ["$$this", { boundary: { $last: "$$value.boundary" }, bucket: { $last: "$$value.bucket" } }] }
                           }
                        }
                     ]
                  ]
               }
            }
         }
      }
   },       
   { $unwind: "$data" }, // transpose array back to documents
   // count the documents by bucket number
   {
      $group: {
         _id: { date: "$data.date", organisationId: "$data.organisationId", bucket: "$data.bucket" },
         ts_min: { $min: "$data.ts" },
         ts_max: { $max: "$data.ts" },
         count: { $sum: 1 }
      }
   },
   // some cosmetic
   { $replaceRoot: { newRoot: { $mergeObjects: ["$$ROOT", "$_id"] } } },
   { $unset: "_id" }
])

请提供一些样本数据。到目前为止,您尝试了什么?这是可能的,但它需要大量的投影计算和阶段,如果您不限制性能,那么复杂性确实不值得。考虑到电视机不会超过你的容量,你最好在内存中完成。如果是这样,您只需对记录进行批量分割。在任何情况下,缓存计算结果。此外,你还依赖于第一条记录的记录时间,对吗?@zhulien yep我依赖于第一条记录,我只需要统计数据所需的信息,所以性能应该不会有问题,因此,例如,如果程序将收集一周的统计数据,这是可以的。Thanx zhulien感谢您的努力。@exStas我实际上已经开始为您提供一个示例解决方案,但小组的范围是(11:55-12:55,12:56-13:56)应该针对每个单独的日期进行计算,也应该跨日期混合,这样会使mongo代码变得非常复杂,所以为了您自己的理智,我会坚持使用off db实施策略。@zhulien如果您愿意,您可以发布答案并给出建议,我将接受。感谢您的努力!我刚刚验证了查询并确认它工作正常!我不完全理解的是为什么我们需要$concatarray在这里运作?它到底在这里干什么?提前谢谢你!我需要构建一个数组,在这里我可以比较当前时间戳和以前的时间戳。如果没有
$concatarray
数据
字段将只具有最后一个值(对于13:04),没有其他值。如果我们在
$group
操作中将文档推入此字段,为什么
数据
字段将为空?