想不出更好的方式比與創建一個附加陣列場集合中具有有序列表的每個文檔。展開該字段並使用$unwind
運算符的includeArrayIndex
屬性來生成索引位置。使用該信息對文檔進行排序,並使用額外的十進制運算符$cond
評估邏輯表達式array element === coreId
,並根據結果返回排序索引(如果爲true),否則返回常量n > order.length
。
下面顯示了上述方法,雖然有很大的改進空間,但至少應該給你一些方向。當然,這將是由你來管道輸送到相應的驅動程序語言轉換(我假設是PHP):
var order = [20, 10];
db.records.aggregate([
{
"$project": {
"coreId" : 1,
"name" : 1,
"sortOrder": { "$literal": order } // create an additional field
}
},
{
"$unwind": {
// flatten the above array
"path": "$sortOrder",
// create the index position for each array element
"includeArrayIndex": "sortIndex",
}
},
{
"$project": {
"coreId": 1,
"name": 1,
"sortIndex": {
"$cond": [
{ "$eq": [ "$coreId", "$sortOrder" ] },
"$sortIndex", 999999
]
}
}
},
{ "$sort": { "sortIndex": 1 } },
{
"$group": {
"_id": "$coreId",
"name": { "$first": "$name" },
"index": { "$first": "$sortIndex" }
}
},
{ "$sort": { "index": 1 } },
{
"$project": {
"_id": 0,
"coreId" : "$_id",
"name" : 1
}
}
])
示例結果
/* 1 */
{
"name" : "a",
"coreId" : 20
}
/* 2 */
{
"name" : "a",
"coreId" : 10
}
/* 3 */
{
"name" : "a",
"coreId" : 30
}