2014-02-27 29 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 
    }) 
    

    這有幫助嗎?有什麼需要進一步澄清?

    相關問題