我有一個非常大的mongodb項目集合,並且我無法更改模式。簡化版本如下所示:
{event: { address: {ip: "1.1.1.1", port: 80}}}
{event: { address: {ip: "1.1.1.2", port: 80}}}
{event: { address: [{ip: "1.1.1.1", port: 80}, {ip: "1.1.1.1", port: 443}]}}
{event: { address: [{ip: "1.1.1.1", port: 8080}, {ip: "1.1.1.2", port: 443}]}}
每個事件可能有一個或多個地址。每個地址都有「ip」和「port」。因此,在多個地址的事件中可能會重複「ip」。
我想要做的就是計算每個IP地址的事件數量,並找到頂部的IP地址。對於上面的例子中,首選的結果是:
[ { "ip" : "1.1.1.1", "count" : 3 },
{ "ip" : "1.1.1.2", "count" : 2 } ]
想到的查詢是這樣的:
db.collection.aggregate({$project: {ip: "$event.address.ip"}}, {$group: {_id: "$ip", count: {$sum: 1}}}, {$sort: {count: -1}}, {$limit: 5})
但結果是:
{
"result" : [
{ "_id" : ["1.1.1.1", "1.1.1.2"], "count" : 1 },
{ "_id" : ["1.1.1.1", "1.1.1.1"], "count" : 1 },
{ "_id" : "1.1.1.2", "count" : 1 },
{ "_id" : "1.1.1.1", "count" : 1 } ],
"ok" : 1
}
我不能用$放鬆因爲每個IP地址應該只計算一次每個事件,但某些事件具有相同的IP重複。另外,$ unwind通常不起作用,因爲「address」並不總是一個數組。有些事件只有一個地址不是數組,而$ unwind會爲它們拋出異常。
我嘗試了不同的聚合運算符,例如$ group中的$ addToSet,但都無濟於事。
該集合非常大,我不能首先提取我的應用程序中的所有IP地址,然後計算每個事件。
是否可以使用map/reduce來完成。你會建議什麼?
它可以用聚合fra完成mework。看到我的答案。 –
@AsyaKamsky這是一個瘋狂的條件數量,你確定如果數據集增長,它仍然會更快? – Sammaye
當然它會更快 - mapreduce也將不得不隨着數據集的增長處理更多的文檔/字段。第一個項目有兩個條件(兩個新領域各有一個),第二個項目有一個條件。這並不「瘋狂」 –