2015-10-28 73 views
3

我有一個用戶收集與以下數據mongodb的組值反之亦然

[ 
    { 
    "user_id": "5625c95ac2d34f27148b64fa", 
    "friend_id": "561f40bac2d34f17148b462c" 
    }, 
    { 
    "user_id": "562744ccc2d34f27148b6eb7", 
    "friend_id": "561f40bac2d34f17148b462c" 
    }, 
    { 
    "user_id": "56248eb9c2d34f2f148b5a18", 
    "friend_id": "561f40bac2d34f17148b462c" 
    }, 
    { 
    "user_id": "561f40bac2d34f17148b462c", 
    "friend_id": "561f3e06c2d34f27148b45f6" 
    }, 
    { 
    "user_id": "561f40bac2d34f17148b462c", 
    "friend_id": "5620de97c2d34f2f148b578f" 
    }, 
    { 
    "user_id": "56276b52c2d34f27148b7128", 
    "friend_id": "561f40bac2d34f17148b462c" 
    }, 
    { 
    "user_id": "561f40bac2d34f17148b462c", 
    "friend_id": "56276b52c2d34f27148b7128" 
    } 
] 

我需要取其中的user_idfriend_id組合不重複的文件。即在上面的例子中,在下一個文件的friend_id中重複的最後兩個文件user_id

我試着用mongo aggrigate和group by但是不能減少它。

+0

請參閱此鏈接http://stackoverflow.com/questions/22932364/mongodb-group-values-by-multiple-fields – Ninju

+0

在這裏我需要消除user_id和friend_id重複反之亦然的文檔。 –

回答

2

要做到這一點,你基本上需要結合user_idfriend_id值在一個獨特的排序組合。這意味着使用這些成員爲每個文檔創建一個數組,並對該數組進行排序,以便順序始終相同。

然後你就可以$group對排序的數組的內容,看看哪些文檔包含相同的組合,然後只返回那些不共享相同的組合。

這導致該聚合聲明:

db.collection.aggregate([ 
    { "$project": { 
     "user_id": 1, 
     "friend_id": 1, 
     "combined": { 
      "$map": { 
       "input": ["A","B"], 
       "as": "el", 
       "in": { 
        "$cond": [ 
         { "$eq": [ "$$el", "A" ] }, 
         "$user_id", 
         "$friend_id" 
        ] 
       } 
      } 
     }    
    }}, 
    { "$unwind": "$combined" }, 
    { "$sort": { "combined": 1 } }, 
    { "$group": { 
     "_id": "$_id", 
     "combined": { "$push": "$combined" }, 
     "user_id": { "$first": "$user_id" }, 
     "friend_id": { "$first": "$friend_id" } 
    }}, 
    { "$group": { 
     "_id": "$combined", 
     "docs": { "$push": { 
      "_id": "$_id", 
      "user_id": "$user_id", 
      "friend_id": "$friend_id" 
     }} 
    }}, 
    { "$redact": { 
     "$cond": { 
      "if": { "$ne": [{ "$size": "$docs" }, 1] }, 
      "then": "$$PRUNE", 
      "else": "$$KEEP" 
     } 
    }} 
]) 

的PHP翻譯laravel意味着需要從經理那裏「收集」是MongoDB中收集的實際名稱訪問原始集合對象:

$result = DB::collection("collection")->raw(function($collection) { 
    return $collection->aggregate(
     array(
      array(
       '$project' => array(
        'user_id' => 1, 
        'friend_id' => 1, 
        'combined' => array(
         '$map' => array(
          'input' => array("A","B"), 
          'as' => 'el', 
          'in' => array(
           '$cond' => array(
            array('$eq' => array('$el', 'A')), 
            '$user_id', 
            '$friend_id' 
           ) 
          ) 
         ) 
        ) 
       ) 
      ), 
      array('$unwind' =>'$combined'), 
      array('$sort' => array('combined' => 1)), 
      array(
       '$group' => array(
        '_id' => '$_id', 
        'combined' => array('$push' => '$combined'), 
        'user_id' => array('$first' => '$user_id'), 
        'friend_id' => array('$first' => '$friend_id') 
       ) 
      ), 
      array(
       '$group' => array(
        '_id' => '$combined', 
        'docs' => array(
         '$push' => array(
          '_id' => '$_id', 
          'user_id' => '$user_id', 
          'friend_id' => 'friend_id' 
         ) 
        ) 
       ) 
      ), 
      array(
       '$redact' => array(
        '$cond' => array(
         'if' => array('$ne' => array(array('$size' => '$docs'), 1)), 
         'then' => '$$PRUNE', 
         'else' => '$$KEEP' 
        ) 
       ) 
      ) 
     ) 
    ); 
}); 

或者,如果你的MongoDB的版本低於2.6,並且你缺乏運營商如$map$redact,那麼你仍然可以做到這一點,但不能有效:

$result = DB::collection("collection")->raw(function($collection) { 
    return $collection->aggregate(
     array(
      array(
       '$project' => array(
        'user_id' => 1, 
        'friend_id' => 1, 
        'type' => array('$const' => array('A', 'B')) 
       ) 
      ), 
      array('$unwind' => '$type'), 
      array(
       '$group' => array(
        '_id' => '$_id', 
        'user_id' => array('$first' => '$user_id'), 
        'friend_id' => array('$first' => '$friend_id'), 
        'combined' => array( 
         '$push' => array(
          '$cond' => array(
           array('$eq' => array('$type', 'A')), 
           '$user_id', 
           '$friend_id' 
          ) 
         ) 
        ) 
       ) 
      ) 
      array('$unwind' =>'$combined'), 
      array('$sort' => array('combined' => 1)), 
      array(
       '$group' => array(
        '_id' => '$_id', 
        'combined' => array('$push' => '$combined'), 
        'user_id' => array('$first' => '$user_id'), 
        'friend_id' => array('$first' => '$friend_id') 
       ) 
      ), 
      array(
       '$group' => array(
        '_id' => '$combined', 
        'docs' => array(
         '$push' => array(
          '_id' => '$_id', 
          'user_id' => '$user_id', 
          'friend_id' => 'friend_id' 
         ) 
        ), 
        'count' => array('$sum' => 1) 
       ) 
      ), 
      array('$match' => array('count' => 1)) 
     ) 
    ); 
}); 

其中前三個階段通過將兩個值放在單個數組中,模擬第一個階段在第一個示例列表中所做的操作。當然,最後兩個階段通過對數組成員進行「計數」,然後進行分組,然後過濾掉沒有「計數」爲1的任何數據。

在此留下您的輸出,僅列出了此組合不會以任何順序發生文檔兩種情況下:

{ 
    "_id" : [ "561f40bac2d34f17148b462c", "5625c95ac2d34f27148b64fa" ], 
    "docs" : [ 
     { 
      "_id" : ObjectId("56306f6cd2387ad4c95b0cc9"), 
      "user_id" : "5625c95ac2d34f27148b64fa", 
      "friend_id" : "561f40bac2d34f17148b462c" 
     } 
    ] 
} 
{ 
    "_id" : [ "561f3e06c2d34f27148b45f6", "561f40bac2d34f17148b462c" ], 
    "docs" : [ 
     { 
      "_id" : ObjectId("56306f6cd2387ad4c95b0ccc"), 
      "user_id" : "561f40bac2d34f17148b462c", 
      "friend_id" : "561f3e06c2d34f27148b45f6" 
     } 
    ] 
} 
{ 
    "_id" : [ "561f40bac2d34f17148b462c", "56248eb9c2d34f2f148b5a18" ], 
    "docs" : [ 
     { 
      "_id" : ObjectId("56306f6cd2387ad4c95b0ccb"), 
      "user_id" : "56248eb9c2d34f2f148b5a18", 
      "friend_id" : "561f40bac2d34f17148b462c" 
     } 
    ] 
} 
{ 
    "_id" : [ "561f40bac2d34f17148b462c", "5620de97c2d34f2f148b578f" ], 
    "docs" : [ 
     { 
      "_id" : ObjectId("56306f6cd2387ad4c95b0ccd"), 
      "user_id" : "561f40bac2d34f17148b462c", 
      "friend_id" : "5620de97c2d34f2f148b578f" 
     } 
    ] 
} 
{ 
    "_id" : [ "561f40bac2d34f17148b462c", "562744ccc2d34f27148b6eb7" ], 
    "docs" : [ 
     { 
      "_id" : ObjectId("56306f6cd2387ad4c95b0cca"), 
      "user_id" : "562744ccc2d34f27148b6eb7", 
      "friend_id" : "561f40bac2d34f17148b462c" 
     } 
    ] 
} 

可以靚起來的輸出,但這種服務的顯示有序的目的與原始文檔數據一起使用的組合。

+0

當我在蒙戈嘗試這個殼它的工作文件,但與laravel它拋出這個錯誤嘗試「例外:組合計字段名‘$ _id’不能是運營商名稱」 –

+0

@RameshPaul在是一個錯字由我PHP列表。糾正。它被正確地顯示在原來的上市以及'「_id」:「$結合」'這哪裏是打字錯誤是。 –

+0

謝謝,現在它正在工作 –