要做到這一點,你基本上需要結合user_id
和friend_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"
}
]
}
可以靚起來的輸出,但這種服務的顯示有序的目的與原始文檔數據一起使用的組合。
請參閱此鏈接http://stackoverflow.com/questions/22932364/mongodb-group-values-by-multiple-fields – Ninju
在這裏我需要消除user_id和friend_id重複反之亦然的文檔。 –