我有一个包含两个字段Grade1
和Grade2
的集合T
,我想选择那些满足条件Grade1 > Grade2
的记录,如何在MySQL中编写查询语句?
Select * from T Where Grade1 > Grade2
您可以使用$where。 只需注意它会相对较慢(必须在每条记录上执行Javascript代码),因此如果可以,请与索引查询结合使用。
db.T.find( { $where: function() { return this.Grade1 > this.Grade2 } } );
更加简洁的写法:
db.T.find( { $where : "this.Grade1 > this.Grade2" } );
你可以使用$expr
,如最近的回答所述。
$expr
比$where
有什么好处吗? - Akaisteph7如果您的查询仅包含$where
操作符,则只需传递JavaScript表达式:
db.T.find("this.Grade1 > this.Grade2");
为了提高性能,运行一个聚合操作,其中包含一个 $redact
pipeline,以过滤满足给定条件的文档。
$redact
pipeline 结合了 $project
和 $match
的功能,实现字段级别的遮蔽。它将使用 $$KEEP
返回所有符合条件的文档,并使用 $$PRUNE
变量从 pipeline 结果中删除不符合条件的文档。
运行以下聚合操作可以更有效地过滤文档,而不是在大集合中使用$where
,因为它使用单个 pipeline 和本地 MongoDB 运算符,而不是 JavaScript 评估和 $where
,这可能会减慢查询速度:
db.T.aggregate([
{
"$redact": {
"$cond": [
{ "$gt": [ "$Grade1", "$Grade2" ] },
"$$KEEP",
"$$PRUNE"
]
}
}
])
这是将两个管道 $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 次循环,最佳循环时间为 192 毫秒每次循环
使用 find 和 $where:
%timeit -n1 -r1 list(coll.find({'$where': 'this.Grade1 > this.Grade2'}))
1次循环,1次最佳结果:每次循环4.54秒
$where: function() { return this.Grade1 - this.Grade2 > variable }
? - Luis Gonzálezdb.T.find({$where: function() {return this.startDate == ISODate("2017-01-20T10:55:08.000Z");}});
时,它没有返回任何结果,即使集合中的一个文档是ISODate("2017-01-20T10:55:08.000Z")
。但是<=
和>=
看起来是有效的。有什么想法吗? - cateyesthis.startDate.getTime() == ISODate("2017-01-20T10:55:08.000Z").getTime()
。 - leinaD_natipaC