集約フレームワークは、 .find()
に適用されるのと同じ方法で配列を「処理」しません。 一般的なクエリ。これは、 .sort()
のような操作だけに当てはまるわけではありません。 、他の演算子、つまり $ slave コード>
、ただし、その例は修正されようとしています(後で)。
したがって、配列位置のインデックスを使用した「ドット表記」形式を使用して、何かを処理することはほとんど不可能です。しかし、これを回避する方法があります。
「できる」ことは、基本的に「n番目」の配列要素が実際に値として何であるかを計算し、それを並べ替え可能なフィールドとして返すことです。
db.test.aggregate([
{ "$unwind": "$items" },
{ "$group": {
"_id": "$_id",
"items": { "$push": "$items" },
"itemsCopy": { "$push": "$items" },
"first": { "$first": "$items" }
}},
{ "$unwind": "$itemsCopy" },
{ "$project": {
"items": 1,
"itemsCopy": 1,
"first": 1,
"seen": { "$eq": [ "$itemsCopy", "$first" ] }
}},
{ "$match": { "seen": false } },
{ "$group": {
"_id": "$_id",
"items": { "$first": "$items" },
"itemsCopy": { "$push": "$itemsCopy" },
"first": { "$first": "$first" },
"second": { "$first": "$itemsCopy" }
}},
{ "$sort": { "second": -1 } }
])
これは恐ろしく「反復可能な」アプローチであり、 $ first
$で処理した後、配列からドキュメントごとに一致しますくつろぐ
。次に、 $ unwind
の後 ここでも、その配列要素が、識別された配列位置からすでに「見られた」ものと同じであるかどうかをテストします。
それはひどいことであり、あなたが一緒に移動したいポジションが多いほど悪くなりますが、結果は得られます:
{ "_id" : 2, "items" : [ 0, 3, 4 ], "itemsCopy" : [ 3, 4 ], "first" : 0, "second" : 3 }
{ "_id" : 1, "items" : [ 1, 2, 0 ], "itemsCopy" : [ 2, 0 ], "first" : 1, "second" : 2 }
{ "_id" : 3, "items" : [ 2, 1, 5 ], "itemsCopy" : [ 1, 5 ], "first" : 2, "second" : 1 }
幸い、MongoDBの今後のリリース(現在開発リリースで利用可能)は、これに対する「修正」を取得します。それはあなたが望む「完璧な」修正ではないかもしれませんが、それは基本的な問題を解決します。
新しい$slave
があります そこで集約フレームワークに使用できる演算子。インデックス付きの位置から配列の必要な要素を返します。
db.test.aggregate([
{ "$project": {
"items": 1,
"slice": { "$slice": [ "$items",1,1 ] }
}},
{ "$sort": { "slice": -1 } }
])
生成するもの:
{ "_id" : 2, "items" : [ 0, 3, 4 ], "slice" : [ 3 ] }
{ "_id" : 1, "items" : [ 1, 2, 0 ], "slice" : [ 2 ] }
{ "_id" : 3, "items" : [ 2, 1, 5 ], "slice" : [ 1 ] }
したがって、「スライス」としての結果は依然として「配列」であることに注意してください。ただし、 $ sort
アグリゲーションフレームワークでは、コンテンツを並べ替えるために、常に配列の「最初の位置」を使用していました。つまり、インデックス付けされた位置から抽出された特異値を使用すると(上記の長い手順と同じように)、結果は期待どおりに並べ替えられます。
ここでのエンドケースは、まさにそれが機能する方法です。アレイのインデックス付きの位置で作業するために上から必要な種類の操作を実行するか、新しい光沢のあるバージョンがより優れたオペレーターで救助されるまで「待機」します。