2017-10-08 78 views
0

我有一個查詢,請在樣本數據集上執行一些聚合後,將下面的示例視爲中間數據;在MongoDB上執行聚合/設置交集

的fileid字段包含文件的ID,以及包含用戶,誰做了一些修改相應的文件

{ 
    「_id」 : { 「fileid」 : 12 }, 
    「_user」 : [ 「a」,」b」,」c」,」d」 ] 
} 
{ 
    「_id」 : { 「fileid」 : 13 }, 
    「_user」 : [ 「f」,」e」,」a」,」b」 ] 
} 
{ 
    「_id」 : { 「fileid」 : 14 }, 
    「_user」 : [ 「g」,」h」,」m」,」n」 ] 
} 
{ 
    「_id」 : { 「fileid」 : 15 }, 
    「_user」 : [ 「o」,」r」,」s」,」v」 ] 
} 
{ 
    「_id」 : { 「fileid」 : 16 }, 
    「_user」 : [ 「x」,」y」,」z」,」a」 ] 
} 
{ 
    「_id」 : { 「fileid」 : 17 }, 
    「_user」 : [ 「g」,」r」,」s」,」n」 ] 
} 

我需要找到這個解決方案的陣列用戶陣列 - >任意兩個用戶是對同一文件中的至少兩個做了一些更改。所以輸出結果應該是

{ 
    「_id」 : { 「fileid」 : [12,13] }, 
    「_user」 : [ 「a」,」b」] 
} 
{ 
    「_id」 : { "fileid」 : [14,17] }, 
    「_user」 : [ 「g」,」n」 ] 
} 
{ 
    「_id」 : { "fileid」 : [15,17] }, 
    「_user」 : [ 「r」,」s」 ] 
} 

您的意見非常感謝。

+0

是不是repoid:[15,17],_user:[「r」,「s」]也是匹配嗎?不要吝嗇;只是想確保示例輸出和描述匹配。 –

+0

是的,我忘了提,那也應該在那裏。 { 「_id」:{「repoid」:[15,17]}, 「_user」:[「r」,「s」] } – user7134427

+0

下面的答案,我相信。 –

回答

0

這是一個有點涉及的解決方案。這個想法是首先使用數據庫來獲得可能配對的總體數量,然後轉而要求數據庫在_user字段中找到配對。請注意,數千名用戶將創建一個非常棒的配對清單。我們使用$addFields以防萬一輸入記錄比我們在示例中看到的要多,但如果不是這樣,爲了提高效率,請使用$project來減少流經管道的物料量。

// 
// Stage 1: Get unique set of username pairs. 
// 
c=db.foo.aggregate([ 
{$unwind: "$_user"} 

// Create single deduped list of users: 
,{$group: {_id:null, u: {$addToSet: "$_user"} }} 

// Nice little double map here creates the pairs, effectively doing this: 
// for index in range(0, len(list)): 
//  first = list[index] 
//  for p2 in range(index+1, len(list)): 
//  pairs.append([first,list[p2]]) 
// 
,{$addFields: {u: 
    {$map: { 
    input: {$range:[0,{$size:"$u"}]}, 
    as: "z", 
    in: { 
     $map: { 
      input: {$range:[{$add:[1,"$$z"]},{$size:"$u"}]}, 
      as: "z2", 
      in: [ 
      {$arrayElemAt:["$u","$$z"]}, 
      {$arrayElemAt:["$u","$$z2"]} 
      ] 
     } 
    } 
    }} 
}} 

// Turn the array of array of pairs in to a nice single array of pairs: 
,{$addFields: {u: {$reduce:{ 
     input: "$u", 
     initialValue:[], 
     in:{$concatArrays: [ "$$value", "$$this"]} 
     }} 
    }} 
      ]); 


// Stage 2: Find pairs and tally up the fileids 

doc = c.next(); // Get single output from Stage 1 above.      

u = doc['u']; 

c2=db.foo.aggregate([ 
{$addFields: {_x: {$map: { 
       input: u, 
       as: "z", 
       in: { 
        n: "$$z", 
        q: {$setIsSubset: [ "$$z", "$_user" ]} 
       } 
      } 
     } 
    }} 
,{$unwind: "$_x"} 
,{$match: {"_x.q": true}} 
// Nice use of grouping by an ARRAY here: 
,{$group: {_id: "$_x.n", v: {$push: "$_id.fileid"}, n: {$sum:1} }} 
,{$match: {"n": {"$gt":1}}} 
        ]); 

show(c2);