想不出更好的方式比与创建一个附加阵列场集合中具有有序列表的每个文档。展开该字段并使用$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
}