マイレージはこれによって異なる場合があり、「現在」あなたがフォローしているプロセスが少なくとも「最も適している」ことが判明する可能性があります。しかし、おそらくもっと効率的にすることができます。
今できること
$ sort
$ push
を使用した修飾子
、その後、おそらくこれを行うことができます:
db.somedb.find(
{
"partn.is_partner": true,
"$where": function() {
return this.partn.slice(-1)[0].is_partner == true;
}
},
{ "partn": { "$slice": -1 } }
)
partn、is_partner
である限り は「インデックス付き」であり、インデックスを使用して初期クエリ条件を満たすことができるため、これは依然としてかなり効率的です。できない部分は、 $ where コード>
ここではJavaScript評価を使用する句。
しかし、 $ where
の2番目の部分は何ですか 実行しているのは、配列から最後の要素を単に「スライス」し、その値を is_partner
でテストすることです。 それが本当かどうかを確認するためのプロパティ。その条件も満たされている場合にのみ、ドキュメントが返されます。
$ slave
もあります。
射影演算子。これは、配列から最後の要素を返す場合にも同じことを行います。偽の一致はすでにフィルタリングされているため、これは真の最後の要素のみを表示しています。
前述のようにインデックスと組み合わせると、ドキュメントがすでに選択されており、JavaScript条件が残りをフィルタリングするだけであるため、これは非常に迅速です。一致する標準のクエリ条件を持つ別のフィールドがない場合、 $ where
句はインデックスを使用できません。したがって、他のクエリ条件を設定した状態で、常に「控えめに」使用するようにしてください。
将来できること
Next Upは、執筆時点では利用できませんが、近い将来、 $ slave
になることは間違いありません。 集約フレームワークの演算子。これは現在開発ブランチにありますが、これがどのように機能するかを見てみましょう:
db.somedb.aggregate([
{ "$match": { "partn.is_partner": true } },
{ "$redact": {
"$cond": {
"if": {
"$anyElementTrue": {
"$map": {
"input": { "$slice": ["$partn",-1] },
"as": "el",
"in": "$$el.is_partner"
}
}
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
{ "$project": {
"partn": { "$slice": [ "$partn",-1 ] }
}}
])
その$辛い
を組み合わせる $ redact
内
ここでのステージでは、ドキュメントを論理条件でフィルタリングし、ドキュメントをテストします。この場合、 $ sense
$に送信される単一要素配列を生成しますマップ
単一のis_partner
を抽出するために 値(まだ配列として)。これはまだせいぜい単一要素の配列であるため、他のテストは <強い>$ anyElementTrue
これは、 に適した、特異なブール結果になります。 $ cond
。
$ redact
ここで、その結果を $$ KEEP
するかどうかを決定します または$$PRUNE
結果からのドキュメント。後で$sense
を使用します プロジェクトで再度、フィルタリング後に配列の最後の要素を返すだけです。
これは、すべてのネイティブコード化演算子を使用していることを除いて、JavaScriptバージョンとほぼ同じであることがわかります。したがって、JavaScriptの代替よりも少し高速である必要があります。
どちらのフォームも、最初のドキュメントを期待どおりに返します:
{
"_id" : 0,
"partn" : [
{
"date" : ISODate("2015-07-28T00:59:14.963Z"),
"is_partner" : true
},
{
"date" : ISODate("2015-07-28T01:00:32.771Z"),
"is_partner" : false
},
{
"date" : ISODate("2015-07-28T01:15:29.916Z"),
"is_partner" : true
},
{
"date" : ISODate("2015-08-05T13:48:07.035Z"),
"is_partner" : false
},
{
"date" : ISODate("2015-08-05T13:50:56.482Z"),
"is_partner" : true
}
]
}
ここでの両方の大きな問題は、配列がすでにソートされている必要があるため、最新の日付が最初になることです。それがなければ、 $ sort
への集約フレームワークが必要です。 今行っているのと同じように、アレイ。
あまり効率的ではないため、アレイを「事前に並べ替え」て、更新のたびに順序を維持する必要があります。
便利なトリックとして、これにより、すべてのコレクションドキュメント内のすべての配列要素が1つの簡単なステートメントで実際に並べ替えられます。
db.somedb.update(
{},
{ "$push": {
"partn": { "$each": [], "$sort": { "date": 1 } }
}},
{ "multi": true }
)
したがって、新しい要素を配列に「プッシュ」してプロパティを更新するだけでなくても、いつでもその基本的な構成を適用して、配列を希望どおりに順序付けておくことができます。
物事をはるかに速くするはずなので、検討する価値があります。