MongoDB-如何根据文档之间的持续时间进行聚合?

MongoDB-如何根据文档之间的持续时间进行聚合?,mongodb,Mongodb,我试图根据事件文档之间的时差将它们聚合到会话文档中: 如果(时差>20分钟)->创建单独的会话 else->合并到同一会话中 我正在研究map-reduce和group&aggregate命令,但还没有找到一个解决方案来实现这一点 条件: 应该是种族条件证明 需要在数据可用时处理数据(不需要按时间顺序排列) 事件之间的最大时间差=20分钟 文档结构: Event = Schema({ start: Date, end: Date, })

我试图根据事件文档之间的时差将它们聚合到会话文档中:

  • 如果(时差>20分钟)->创建单独的会话
  • else->合并到同一会话中
我正在研究map-reduce和group&aggregate命令,但还没有找到一个解决方案来实现这一点

条件

  • 应该是种族条件证明
  • 需要在数据可用时处理数据(不需要按时间顺序排列)
  • 事件之间的最大时间差=20分钟
文档结构

    Event = Schema({
      start: Date,
      end: Date,
    })

    Session = Schema({
      start: Date,
      end: Date,
      duration: Number //will be an aggregate for the time of the events, ignoring the time in between
    })
迄今为止的最佳解决方案(效率不高且不符合竞争条件)

    Event = Schema({
      start: Date,
      end: Date,
    })

    Session = Schema({
      start: Date,
      end: Date,
      duration: Number //will be an aggregate for the time of the events, ignoring the time in between
    })
对于每个
新事件={start,finish}

    1. matched_events = Sessions.find{ start:{$lt:new_event.finish+20*60*1000},finish:{$gt:new_event.start-20*60*1000}, 
    2. new_session = {start: $min:{matched_events.start}, finish: $max:{matched_events.finish}}

有什么想法吗?

为了满足在向集合中添加新数据时实时响应的要求,您可以使用MongoDB复制oplog。oplog记录对数据库的每次写入,通常用于允许副本集中的二级副本跟随对主副本的写入,并将写入应用于次副本上的副本。但是,其他应用程序也可以使用它来监视数据库的更新

要使用它,您需要将mongod设置为副本集,这将启用oplog记录。如果不需要数据复制功能,则可以是单节点副本集。有关如何将独立mongod实例转换为单节点副本集的说明,请参阅。简言之,您可以指定--replSet选项重新启动mongod,然后连接Mongoshell并执行rs.initiate()

完成此操作后,您现在有了一个oplog,它在“local”数据库中显示为“oplog.rs”。一旦有了oplog,就可以创建一个用于监视写入操作的。可裁剪游标在概念上类似于Unix tail-f命令:它为添加到其监视的capped集合中的每个文档接收一个新结果

在mongo壳中,它看起来像这样;其他语言驱动程序具有类似的功能:

tailable = DBQuery.Option.tailable + DBQuery.Option.awaitData
db.oplog.rs.find({}).addOption(tailable).forEach(function (d) {
    print('--- op', d.op, 'ns', d.ns)
    printjson(d.o)
    // application logic goes here
})
每次写操作发生时,您都会得到一个新文档,其中包含多个详细说明写操作的字段。你特别感兴趣的是

  • op字段,指示写入是插入还是更新;您可能对insert感兴趣,因为op字段的值为'i'
  • ns字段,指示对其进行写入的命名空间(数据库和集合)
  • o字段,它是新的对象值
例如,前面的程序为插入的每个新文档打印以下内容:

--- op i ns test.c
{ "_id" : ObjectId("5310a0a0ca57fb03897318f8"), "hello" : "world" }
然后,您将在该循环中添加所需的聚合逻辑,检查插入的对象以确定如何将其与以前的文档聚合,可能会将聚合的文档插入到数据库中

您可以在find()中指定查询词,以确保只看到感兴趣的事件。例如,此版本将只在“测试”数据库的“c”集合上提供插入:

tailable = DBQuery.Option.tailable + DBQuery.Option.awaitData
db.oplog.rs.find({op:'i', ns:'test.c'}).addOption(tailable).forEach(function (d) {
    // application logic goes here
})

这有用吗?有什么需要进一步澄清的吗?

您试图做什么?向我们展示一些代码,了解您遇到的问题,这将帮助我们解决问题。我正在查看mongodb中可用的不同命令,无法找到动态使用事件之间持续时间进行聚合的方法。目前,我的最佳想法是使用查询($gt,$lt运算符)在mongodb之外进行聚合,然后写回mongo,但这样我就可以遇到竞争条件,这将创建多个会话。我明白了,您是否可以发布一个文档示例?我不认为
mapreduce
能够自己解决这个问题。添加了更多信息。谢谢你迄今为止的帮助!为什么不投票?这个问题怎么了?