ご存知のとおり、$ Sliceは、結果で返される配列要素を制限するための射影でのみ使用されます。そのため、find()の結果を使用してプログラムでリストを処理することに固執することになります。
より良いアプローチは、集計を使用することです。ただし、最初に $ slaveについて考えてみましょう。 使用される:
> db.collection.find({},{ relevancy: {$slice: -1} })
{ "_id" : ObjectId("530824b95f44eac1068b45c0"), "relevancy" : [ "Y" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c2"), "relevancy" : [ "Y" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c3"), "relevancy" : [ "N" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c4"), "relevancy" : [ "Y" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c6"), "relevancy" : [ "N" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c7"), "relevancy" : [ "N" ] }
{ "_id" : ObjectId("530824b95f44eac1068b45c8"), "relevancy" : [ "N" ] }
したがって、最後の配列要素を取得しますが、一致できないため、結果のループにとどまります。 最後の要素の値。これをコードで行った方がよいでしょう。
それでは、集計を見てみましょう。 :
db.collection.aggregate([
// Match things so we get rid of the documents that will never match, but it will
// still keep some of course since they are arrays, that *may* contain "N"
{ "$match": { "relevancy": "Y" } },
// De-normalizes the array
{ "$unwind": "$relevancy" },
// The order of the array is retained, so just look for the $last by _id
{ "$group": { "_id": "$_id", "relevancy": { "$last": "$relevancy" } }},
// Match only the records with the results you want
{ "$match": { "relevancy": "Y" }},
// Oh, and maintain the original _id order [ funny thing about $last ]
{ "$sort": { "_id": 1 } }
])
これがaggregate()の最初の使用法である場合でも、学ぶことをお勧めします。 。それはおそらくあなたの最も有用な問題解決ツールです。確かに私にとってはそうです。各ステップを1回に入れます 一度に学習している場合。
また、ドキュメントフォームで、すべての1: { ... }
がわからない サブドキュメントの表記は間違いのようですが、それをクリアするか、上記のコードを調整して"1.relevancy"
を参照する必要があります。 代わりは。ただし、実際にはドキュメントが次のようになっていることを願っています:
{ "relevancy" : [ "Y" ] , "_id" : ObjectId("530824b95f44eac1068b45c0") }
{ "relevancy" : [ "Y", "Y" ] , "_id" : ObjectId("530824b95f44eac1068b45c2") }
{ "relevancy" : [ "N" ], "_id" : ObjectId("530824b95f44eac1068b45c3") }
{ "relevancy" : [ "Y", "Y" ], "_id" : ObjectId("530824b95f44eac1068b45c4") }
{ "relevancy" : [ "Y", "N" ], "_id" : ObjectId("530824b95f44eac1068b45c6") }
{ "relevancy" : [ "N" ], "_id" : ObjectId("530824b95f44eac1068b45c7") }
{ "relevancy" : [ "Y", "N" ], "_id" : ObjectId("530824b95f44eac1068b45c8") }
MongoDB3.2.x以降
もちろん、MongoDB 3.2では、$slice
に「aggregation」演算子が導入されています。 さらに優れた$arrayElemAt
$unwind
の必要性を排除する演算子 および$group
処理。最初の$match
の後 $redact
と「論理的に一致」するだけのクエリ :
db.collection.aggregate([
{ "$match": { "relevancy": "Y" } },
{ "$redact": {
"$cond": {
"if": { "$eq": [{ "$arrayElemAt": [ "$relevancy", -1 ], "Y" ] },
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
これにより、$$KEEP
を実行するかどうかを決定するときに、配列の最後の要素が検査されます。 または$$PRUNE
返された結果からのドキュメント。
それでも「プロジェクション」が必要な場合は、実際に$slice
を追加できます。 :
db.collection.aggregate([
{ "$match": { "relevancy": "Y" } },
{ "$redact": {
"$cond": {
"if": { "$eq": [{ "$arrayElemAt": [ "$relevancy", -1 ], "Y" ] },
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
{ "$project": { "relevancy": { "$slice": [ "$relevancy", -1 ] } } }
])
または、次の代替アプローチ:
db.collection.aggregate([
{ "$match": { "relevancy": "Y" } },
{ "$project": { "relevancy": { "$slice": [ "$relevancy", -1 ] } } },
{ "$match": { "relevancy": "Y" } }
])
ただし、$redact
を実行する方がおそらくコストがかかりません。 最初に「次に」、`$projectで再形成を行います。