回答:
$ whereを使用できます。かなり遅い(すべてのレコードでJavascriptコードを実行する必要がある)ので、可能であればインデックス付きクエリと組み合わせてください。
db.T.find( { $where: function() { return this.Grade1 > this.Grade2 } } );
以上のコンパクト:
db.T.find( { $where : "this.Grade1 > this.Grade2" } );
最近の回答で$expr
説明されているように使用できます
$where: function() { return this.Grade1 - this.Grade2 > variable }
ですか?
db.T.find({$where: function() {return this.startDate == ISODate("2017-01-20T10:55:08.000Z");}});
それを試みたときに何も返さない、コレクション内のドキュメントの1つでさえもですISODate("2017-01-20T10:55:08.000Z")
。しかし<=
、>=
仕事のようです。何か案が?
this.startDate.getTime() == ISODate("2017-01-20T10:55:08.000Z").getTime()
あなたは使用することができます$ exprの定期的なクエリで集計関数を使用する(3.6のmongoバージョン演算子を)。
比較query operators
対aggregation comparison operators
。
通常のクエリ:
db.T.find({$expr:{$gt:["$Grade1", "$Grade2"]}})
集計クエリ:
db.T.aggregate({$match:{$expr:{$gt:["$Grade1", "$Grade2"]}}})
クエリが$where
演算子のみで構成されている場合は、JavaScript式のみを渡すことができます。
db.T.find("this.Grade1 > this.Grade2");
パフォーマンスを向上させるには、$redact
パイプラインを含む集計操作を実行して、特定の条件を満たすドキュメントをフィルタリングします。
$redact
パイプラインはの機能を組み込んだ$project
し、$match
それが使用条件に合致するすべての文書を返しますフィールドレベルの改訂実装するために$$KEEP
パイプラインの結果から、使用して一致しないものと削除し$$PRUNE
、変数を。
次の集約操作を実行すると$where
、大規模なコレクションを使用するよりも効率的にドキュメントをフィルタリング$where
できます。これは、によるJavaScript評価ではなく、単一のパイプラインとネイティブのMongoDB演算子を使用するため、クエリが遅くなる可能性があります。
db.T.aggregate([
{
"$redact": {
"$cond": [
{ "$gt": [ "$Grade1", "$Grade2" ] },
"$$KEEP",
"$$PRUNE"
]
}
}
])
これは2つのパイプラインを組み込んでいるのがより簡略化されたバージョンである$project
と$match
:
db.T.aggregate([
{
"$project": {
"isGrade1Greater": { "$cmp": [ "$Grade1", "$Grade2" ] },
"Grade1": 1,
"Grade2": 1,
"OtherFields": 1,
...
}
},
{ "$match": { "isGrade1Greater": 1 } }
])
MongoDB 3.4以降:
db.T.aggregate([
{
"$addFields": {
"isGrade1Greater": { "$cmp": [ "$Grade1", "$Grade2" ] }
}
},
{ "$match": { "isGrade1Greater": 1 } }
])
可読性よりもパフォーマンスが重要な場合、条件が単純な算術演算で構成されている限り、集約パイプラインを使用できます。最初に、$ projectを使用して条件の左側を計算します(すべてのフィールドを左側に移動します)。次に、$ matchを使用して定数とフィルターと比較します。これにより、JavaScriptの実行を回避できます。以下はPythonでの私のテストです:
import pymongo
from random import randrange
docs = [{'Grade1': randrange(10), 'Grade2': randrange(10)} for __ in range(100000)]
coll = pymongo.MongoClient().test_db.grades
coll.insert_many(docs)
集計の使用:
%timeit -n1 -r1 list(coll.aggregate([
{
'$project': {
'diff': {'$subtract': ['$Grade1', '$Grade2']},
'Grade1': 1,
'Grade2': 1
}
},
{
'$match': {'diff': {'$gt': 0}}
}
]))
1ループ、最高1:ループあたり192 ms
検索と$ whereの使用:
%timeit -n1 -r1 list(coll.find({'$where': 'this.Grade1 > this.Grade2'}))
1ループ、最高1:ループあたり4.54秒