2014-02-27 28 views
0

我试图聚集基于它们之间的时间差事件文件到会议文件:MongoDB - 如何基于文档之间的持续时间进行聚合?

  • 如果(时间差> 20分钟) - >创建单独的会话
  • 其他 - >合并到同一个会话

我正在查看map-reduce和组&聚合命令,但还没有拿出让我这样做的解决方案。

条件

  • 应该是比赛条件证明
  • 将需要处理的数据变得可用(不必按时间顺序)= 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 
        }) 
    

    最好的解决方案至今(效率不高&赛马不相条件证明)

    ,每new_event = {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}} 
    

    任何想法?

  • +0

    你试过做什么?向我们展示一些关于卡住的地方的代码,这将帮助我们找出问题所在。 – Roberto

    +0

    我正在查看mongodb中可用的不同命令,无法找到动态使用事件间持续时间进行聚合的方法。 目前我最好的想法是通过使用查询($ gt,$ lt operators)在mongodb之外进行聚合并回写到mongo,但是然后我可以运行竞争条件,这会创建多个会话。 – tobyai

    +0

    我明白了,你会发布一个文件的例子吗?我不认为'mapreduce'能够自己把这件事情弄清楚。 – Roberto

    回答

    1

    为了满足在将新数据添加到集合中时实时响应的需求,可以使用MongoDB复制oplog。 oplog记录每次写入数据库,并且通常用于允许副本集中的辅助节点对主节点执行写操作,并将写操作应用于辅助节点上的副本。但是,其他应用程序也可以使用它来监视数据库的更新。

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

    完成此操作后,您现在有一个oplog,在“本地”数据库中显示为“oplog.rs”capped collection。一旦你有了一个oplog,你就可以创建一个tailable cursor来监控写入操作。可放大光标在概念上类似于Unix tail -f命令:它会为添加到正在监视的上限集合中的每个文档接收一个新结果。

    在mongo shell中,它看起来像这样;其他语言的司机也有类似的功能:

    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字段,它指示写入是插入还是更新;可能你对嵌入感兴趣,对此op域的值为'i'
    • ns字段,它指示写入完成的名称空间(数据库和集合)
    • o字段,它是新对象值

    因此,例如,根据前述程序打印对于插入的每个新的文档的以下内容:

    --- op i ns test.c 
    { "_id" : ObjectId("5310a0a0ca57fb03897318f8"), "hello" : "world" } 
    

    你会再加入所需的聚集逻辑这个循环中,检查所插入的对象,以确定如何汇总我t与以前的文档,因此可能会将聚合文档插入到数据库中。

    您可以在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 
    }) 
    

    这有帮助吗?有什么需要进一步澄清?

    相关问题