2012-11-22 85 views
0

我有一個集合稱爲 「事件」,看起來像這樣:地圖減少的MongoDB:_id問題

{ 
     "_id" : ObjectId("4fd89f8d3cbec825d7000001"), 
     "type" : "lms_course_view", 
     "datetime" : ISODate("2011-12-23T12:55:00Z"), 
     "user" : [ 
       { 
         "_id" : ObjectId("4fd89f8d3cbec825d7000000") 
       } 
     ] 
} 

而另外一個被稱爲 「用戶」,具體如下:

{ 
     "_id" : ObjectId("4fd89f8d3cbec825d7000000"), 
     "name" : "02ad1046f", 

     (...) 
} 

我試圖計算每個用戶製作每種事件類型的次數。我用的map-reduce很努力,但我不知道如何創建一個映射函數在事件迭代,同時發出用戶名(存儲在不同的集合)。

任何線索?用map-reduce可以嗎?

+1

這是可能的,但你必須做兩個MapReduce的,你可以找到一個樣本[這裏](http://tebros.com/2011/07/using-mongodb-mapreduce-to-join-2-collections /)。 – Eric

+0

是否有用戶名不在事件集合中的原因?您可能會考慮反規範化您的模式,以便將該名稱添加到用戶數組中。 –

回答

1

由於您的用戶名從events收集分開存儲,你需要做兩道無妨。我建議使用Aggregation Framework然後轉換到user["_id"]user["name"]在第二遍。彙總框架代碼可能如下所示:

db.events.aggregate(
    { $unwind: "$user" }, // breaks apart user array into separate documents 
    { $group: { 
     _id: { user: "$user._id", type: "$type" } 
     count: { $sum: 1 } 
    } } 
); 
+0

太好了。它工作正常。非常感謝你。我不知道聚合框架。實際上,我正在使用版本2.0(來自ubuntu的宇宙庫)。 – lfuente

0

您的模式似乎對您所述的用例構造不佳。

我建議重新考慮它與非規範化的用戶名進入的事件集合。

我認爲用戶領域是一個數組,因爲多個用戶可以製作每個事件 - 在這種情況下,它仍然是一個數組,但每個元素將有兩個領域 - _id像現在這樣表示的名字加名的用戶。這是相對「安全」的,因爲用戶名不經常改變(如果有的話)。

一旦你有了這個模式,你可以選擇使用MapReduce(發出{用戶名,事件類型}作爲鍵),或者你可以用@slee在他的回答中描述的方式使用聚合框架。

+0

我同意,我的架構建造不爲我的使用情況。無論如何,這是我的,我會盡量充分利用它。正如@slee所說,我需要兩次傳球。 – lfuente