この質問は古いことは知っていますが、同様の新しい質問 に回答した後にGoogleで見つけました。 。だから私はこれが同じ治療に値すると思いました。
$where のパフォーマンスへの影響を回避できます 集計 を使用する 代わりに:
db.example.aggregate([
// Use an index, which $where cannot to narrow down
{$match: { "comments.by": "Abe" }},
// De-normalize the Array
{$unwind: "$comments"},
// The order of the array is maintained, so just look for the $last by _id
{$group: { _id: "$_id", comments: {$last: "$comment"} }},
// Match only where that $last comment by `by.Abe`
{$match: { "comments.by": "Abe" }},
// Retain the original _id order
{$sort: { _id: 1 }}
])
そして、それは $ whereの周りでリングを実行する必要があります 持っていたドキュメントを絞り込むことができたので そもそも「阿部」のコメント。警告どおり、 $ where コレクション内のすべてのドキュメントをテストし、使用するドキュメントがある場合でもインデックスを使用しないようにします。
もちろん、ここで説明する手法
を使用して元のドキュメントを維持することもできます。 同様に、すべてが find()
のように機能します 。
これを見つけた人のための単なる思考の糧。
最新のMongoDBリリースのアップデート
最新のリリースでは、 $ redact
が追加されています。
パイプライン式と $ arrayElemAt
(後者は3.2の時点で、ここでは最小バージョンになります)これを組み合わせることで、論理式が $ unwind
ステージ:
db.example.aggregate([
{ "$match": { "comments.by": "Abe" }},
{ "$redact": {
"$cond": {
"if": {
"$eq": [
{ "$arrayElemAt": [ "$comments.by", -1 ] },
"Abe"
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
ここでのロジックは、 $ arrayElemAt
>
配列の最後のインデックスを取得しています-1
、 "by"
の値の配列に変換されます $ map
経由のプロパティ
。これにより、単一の値を必要なパラメーター "Abe"
と比較できます。 。
または、 $ expr
を使用して、もう少し現代的なものにします。
MongoDB 3.6以降の場合:
db.example.find({
"comments.by": "Abe",
"$expr": {
"$eq": [
{ "$arrayElemAt": [ "$comments.by", -1 ] },
"Abe"
]
}
})
これは、配列内の最後の要素を照合するための最もパフォーマンスの高いソリューションであり、実際には $ where
ほとんどの場合、特にここで。