2015-03-03 52 views
2

我有一個帶有標籤子文檔的文檔集合。 用mongodb聚合查詢獲取子文檔中的同胞數量

{ 
    title:"my title", 
    slug:"my-title", 
    tags:[ 
     {tagname:'tag1', id:1}, 
     {tagname:'tag2', id:2}, 
     {tagname:'tag3', id:3}] 
} 
{ 
    title:"my title2", 
    slug:"my-title2", 
    tags:[ 
     {tagname:'tag1', id:1}, 
     {tagname:'tag2', id:2}] 
} 
{ 
    title:"my title3", 
    slug:"my-title3", 
    tags:[ 
     {tagname:'tag1', id:1}, 
     {tagname:'tag3', id:3}] 
} 
{ 
    title:"my title4", 
    slug:"my-title4", 
    tags:[ 
     {tagname:'tag1', id:1}, 
     {tagname:'tag2', id:2}, 
     {tagname:'tag3', id:3}] 
} 

[...]

獲取每一個標籤的計數與$開卷+組相當簡單算總

不過,我想尋找一種標籤的數被發現在一起,或者更確切地說,哪個兄弟姐妹通常在彼此旁邊出現,按伯爵排序。我還沒有找到一個例子,我也不知道如何做到這一點沒有多個查詢。

理想情況下,最終的結果將是:

{'tag1':{ 
    'tag2':3, // tag1 and tag2 were found in a document together 3 times 
    'tag3':3, // tag1 and tag3 were found in a document together 3 times 
    [...]}} 

{'tag2':{ 
    'tag1':3, // tag2 and tag1 were found in a document together 3 times 
    'tag3':2, // tag2 and tag3 were found in a document together 2 times 
    [...]}} 

{'tag3':{ 
    'tag1':3, // tag3 and tag1 were found in a document together 3 times 
    'tag2':2, // tag3 and tag2 were found in a document together 2 times 
    [...]}} 

[...] 
+0

我認爲你的意思是''標籤「:[{}]'因爲與你輸入的內容相比,這將是數組語法,這實際上不是有效的文檔結構。您不能使用聚合框架創建任意「關鍵名稱」。它也似乎不可能得到你想要的結果(或接近它),但我真的只是猜測,因爲你的問題缺乏一個明確的樣本,可能產生一個明確的預期結果。請參閱:[如何創建一個最小,完整和可驗證的示例](http://stackoverflow.com/help/mcve) – 2015-03-03 01:36:51

+0

這只是簡化的非手工操作,原始文檔相當大,子文檔也非常大。 – tweak2 2015-03-03 01:57:48

+0

看到你糾正了數組符號。不要求你提交整件事,只是樣本和實際可能從樣本數據中獲得(需要)的結果。它使你的問題比現在更清晰。 – 2015-03-03 02:07:44

回答

1

如前所述,它只是簡單地是不可能有聚合框架生成的數據任意鍵名。在單個查詢中進行這種分析也是不可能的。

但是有一種通用的方法可以在您的整個集合中爲未定數目的標籤名稱執行此操作。基本上,您將需要獲得「標籤」的不同列表,並處理針對每個不同值的另一個查詢,以獲得該標籤和計數的「兄弟」。

一般:

// Get a the unique tags 
db.collection.aggregate([ 
    { "$unwind": "$tags" }, 
    { "$group": { 
     "_id": "$tags.tagname" 
    }} 
]).forEach(function(tag) { 
    var tagDoc = { }; 
    tagDoc[tag._id] = {}; 

    // Get the siblings count for that tag 
    db.collection.aggregate([ 
     { "$match": { "tags.tagname": tag._id } }, 
     { "$unwind": "$tags" }, 
     { "$match": { "tags.tagname": { "$ne": tag._id } } }, 
     { "$group": { 
      "_id": "$tags.tagname", 
      "count": { "$sum": 1 } 
     }} 
    ]).forEach(function(sibling) { 
      // Set the value in the master document 
      tagDoc[tag._id][sibling._id] = sibling.count; 
    }); 
    // Just emitting for example purposes in some way 
    printjson(tagDoc); 
}); 

的聚合框架可以返回版本光標因爲MongoDB的2.6,因此即使有大量標籤這可以以高效的方式工作。

所以這就是你處理這個問題的方式,但是真的沒有辦法在單個查詢中發生這種情況。對於較短的運行時間,您可以查看允許多個查詢並行運行的框架,可以將結果合併或發佈到流。

+0

這與我之前的方法類似,這是一個獨特的查詢,然後是放鬆和組。有沒有辦法做到這一點在一個單一的聚合? – tweak2 2015-03-04 18:28:03

+0

@ tweak2不可以,因爲在這裏的答案中已經描述過的原因,不可能一次完成。還要注意的是'.distinct()'命令返回一個數組而不是一個遊標的區別,所以您可以獲得的結果的大小有限制。使用遊標和輸出流消除了限制。也'。distanct()不能根據實際的「兄弟姐妹」的需要「過濾」數組內容。 – 2015-03-04 23:12:31