2017-10-08 9 views
0

サンプルデータセットでいくつかの集計を実行した後、中間データとして次の例を考えます。MongoDBで集計/集合交叉を実行

FILEIDフィールドが

それぞれのファイルに
{ 
    “_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、およびいくつかの変更を行ったユーザのユーザ配列含む配列が含まれている私は、このための解決策を見つける必要がある - >任意の二人のユーザこと同じファイルの少なくとも2つにいくつか変更を加えました。出力結果は

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

となるはずです。

+0

[15,17]、_user:["r"、 "s"]も一致しますか?ニックピックではありません。サンプルの出力と説明が一致していることを確認したいだけです。 –

+0

はい、忘れましたが、そこにもあるはずです。 { "_id":{"repoid":[15,17]}、 "_user":["r"、 "s"] } – user7134427

+0

以下の回答は、私が信じています。 –

答えて

0

これはやや複雑な解決策です。最初にDBを使用して可能なペアの母集団を取得した後、方向を変えて_userフィールドにペアを見つけるようDBに依頼します。 1000人のユーザーが大きなペアリングリストを作成することに注意してください。この例では入力レコードのほうが多い場合に備えて$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);