基本的な.find()
の形式では、条件に一致する配列の複数の要素を返すことはできません。 クエリ。複数の要素を照合するには、.aggregate()
を使用する必要があります 代わりにメソッド。
ここでの主な違いは、「クエリ」が意図したとおりに実行され、条件に一致する「ドキュメント」と一致することです。位置$
の使用を試みることができます 射影引数内の演算子ですが、クエリ条件に一致する「最初の」配列要素にのみ一致するという規則があります。
複数の配列要素を「フィルタリング」するには、次の手順に従います。
db.sample.aggregate([
// Filter possible documents
{ "$match": { "filtermetric.class": "s2" } },
// Unwind the array to denormalize
{ "$unwind": "$filtermetric" },
// Match specific array elements
{ "$match": { "filtermetric.class": "s2" } },
// Group back to array form
{ "$group": {
"_id": "$_id",
"filtermetric": { "$push": "$filtermetric" }
}}
])
バージョン2.6以降のMongoDBの最新バージョンでは、 $redact
を使用してこれを行うことができます。 :
db.sample.aggregate([
// Filter possible documents
{ "$match": { "filtermetric.class": "s2" } },
// Redact the entries that do not match
{ "$redact": {
"$cond": [
{ "$eq": [ { "$ifNull": [ "$class", "s2" ] }, "s2" ] },
"$$DESCEND",
"$$PRUNE"
]
}}
])
これはおそらく最も効率的なオプションですが、再帰的であるため、最初にドキュメント構造を検討してください。同じ名前のフィールドは、他のどのレベルの条件でも存在できないためです。
おそらくより安全ですが、配列の結果が「本当にユニーク」である場合にのみ役立つのは、 $map
を使用したこの手法です。 および$setDifference
:
db.sample.aggregate([
{ "$project": {
"filtermetric": { "$setDifference": [
{ "$map": [
"input": "$filtermetric",
"as": "el",
"in": {"$cond": [
{ "$eq": [ "$$el.class", "s2" ] },
"$$el",
false
]}
]},
[false]
]}
}}
])
また、 $group
の両方で注意してください および$project
必要の運用パイプラインステージ その段階から結果ドキュメントに返す予定のすべてのフィールドを指定します。
最後の注意点は、 $elemMatch
配列内の単一のキーの値のみを照会する場合は必要ありません。アレイの単一のキーにのみアクセスする場合は、「ドット表記」をお勧めします。 $elemMatch
配列「element」内のドキュメント内の「複数の」キーがクエリ条件に一致する必要がある場合にのみ必要です。