2013-03-08 133 views
0

我一直在使用下面的MySQL命令從日誌數據構造一個熱圖。但是,我有一個存儲在Mongo數據庫中的新數據集,我需要運行相同的命令。從MySQL查詢生成Mongo查詢

select concat(a.packages '&' b.packages) "Concurrent Packages", 
count(*) "Count" 
from data a 
cross join data b 
where a.packages<b.packages and a.jobID=b.jobID 
group by a.packages, b.packages 
order by a.packages, b.packages; 

請記住,表a和表b在查詢之前不存在。但是,它們是從數據表的包列中創建的,其中jobID作爲我想檢查匹配項的字段。換句話說,如果兩個包在同一個作業中,我想爲併發使用計數添加一個條目。我如何在Mongo中生成一個類似的查詢?

+2

你嘗試過什麼?你看過[這個](http://docs.mongodb.org/manual/reference/sql-aggregation-comparison/)頁面的靈感? – WiredPrairie 2013-03-08 02:52:30

回答

1

你不能。 Mongo不會加入。從SQL切換到Mongo比遷移查詢涉及更多。

通常情況下,您需要將所有相關信息包含在同一條記錄中(而不是規範化信息並通過聯接進行選擇)。非規範化!

+0

所以你告訴我的是,沒有辦法查詢MongoDB來計算2個包被用作同一個工作的一部分的次數。不知何故,我覺得很難相信。 – amber4478 2013-03-08 02:23:51

+0

這不是我要說的。我的意思是說你實際上會緩存這個值,並將其保存爲有問題的工作記錄(如果你正在計算某個特定工作或任何有兩個包的工作,我仍然有點模糊) – landons 2013-03-08 02:38:53

+0

任何工作多個包運行,我想存儲在同一個工作中使用的每對包的計數。例如,如果我有packageA和packageB,並且它們被同時用作20個工作的一部分。我想要一個查詢,它返回每一對包被用作同一作業一部分的次數。 – amber4478 2013-03-08 02:48:50

2

這不是「加入」的不同文件;它是一個文件中的一個操作,並且可以在MongoDB中完成。

You have a SQL TABLE "data" like this: 
    JobID TEXT, 
    package TEXT 

到這些信息存儲在MongoDB中,最好的辦法將是一個集合稱爲「數據」,包含每個作業ID一個文檔,包含封裝陣列:

{ 
    _id: <JobID>, 
    packages: [ 
     "packageA", 
     "packageB", 
     .... 
    ] 
} 

[注:你也可以實現你的數據表只能作爲MongoDB中的一個文檔,包含一個包含每個軟件包數組的作業數組。這是不推薦的,因爲你可能會遇到16MB的文檔大小限制,並且嵌套數組還沒有被不同的查詢很好地支持 - 如果你想將數據用於其他目的,那麼]

現在,如何獲取像這樣的結果?

{ pair: [ "packageA", "packageB" ], count: 20 }, 
{ pair: [ "packageA", "packageC" ], count: 11 }, 
... 

由於沒有內置的「交叉連接」 MongoDB中兩個數組的,你得出來的MapReduce的()的地圖功能項目,分別發出對包作爲重點:

mapf = function() { 
    that = this; 
    this.packages.forEach(function(p1) { 
     that.packages.forEach(function(p2) { 
      if (p1 < p2) { 
       key = { "pair": [ p1, p2 ] }; 
       emit(key, 1); 
      }; 
     }); 
    }); 
}; 

[注:這可能是最優化,如果封裝陣列,分類]

的降低作用無非是爲每個按鍵計數器總結以上:

reducef = function(key, values) { 
    count = 0; 
    values.forEach(function(value) { count += value }); 
    return count; 
}; 

所以,在這個例子中採集:

> db.data.find() 
{ "_id" : "Job01", "packages" : [ "pA", "pB", "pC" ] } 
{ "_id" : "Job02", "packages" : [ "pA", "pC" ] } 
{ "_id" : "Job03", "packages" : [ "pA", "pB", "pD", "pE" ] } 

we get the following result: 

> db.data.mapReduce(
...  mapf, 
...  reducef, 
...  { out: 'pairs' } 
...); 
{ 
    "result" : "pairs", 
    "timeMillis" : 443, 
    "counts" : { 
     "input" : 3, 
     "emit" : 10, 
     "reduce" : 2, 
     "output" : 8 
    }, 
    "ok" : 1, 
} 
> db.pairs.find() 
{ "_id" : { "pair" : [ "pA", "pB" ] }, "value" : 2 } 
{ "_id" : { "pair" : [ "pA", "pC" ] }, "value" : 2 } 
{ "_id" : { "pair" : [ "pA", "pD" ] }, "value" : 1 } 
{ "_id" : { "pair" : [ "pA", "pE" ] }, "value" : 1 } 
{ "_id" : { "pair" : [ "pB", "pC" ] }, "value" : 1 } 
{ "_id" : { "pair" : [ "pB", "pD" ] }, "value" : 1 } 
{ "_id" : { "pair" : [ "pB", "pE" ] }, "value" : 1 } 
{ "_id" : { "pair" : [ "pD", "pE" ] }, "value" : 1 } 

欲瞭解更多信息,MapReduce的諮詢:http://docs.mongodb.org/manual/reference/method/db.collection.mapReduce/http://docs.mongodb.org/manual/applications/map-reduce/