2017-10-08 14 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

[15,17], _user : [ "r", "s"]도 일치합니까? 닉 피킹하지 않음; 샘플 출력과 설명이 일치하는지 확인하기 만하면됩니다. –

+0

예, 잊어 버렸습니다. 또한 거기에 있어야합니다. { "_id": { "repoid": [15,17]}, "_user": [ "r", "s"] } – user7134427

+0

아래 답변은 믿습니다. –

답변

0

다소 복잡한 해결책입니다. 먼저 DB를 사용하여 가능한 쌍의 인구를 얻은 다음 뒤돌아 DB에 _user 필드에서 쌍을 찾으라고 요청하는 것입니다. 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);