順序付けられたリストを持つコレクション内の各ドキュメントで追加の配列フィールドを作成するよりも優れた方法は考えられません。そのフィールドを巻き戻しincludeArrayIndex
、演算子のプロパティを使用し$unwind
てインデックス位置を生成します。その情報を使用してドキュメントを並べ替え、追加の 10 項演算子を使用$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
}