我有一个集合T,有2个字段:Grade1而且Grade2,我想选择那些有条件的Grade1 > Grade2,我怎样才能得到像MySQL一样的查询?
Select * from T Where Grade1 > Grade2
Run Code Online (Sandbox Code Playgroud)
小智 114
你可以使用$ where.请注意,它会相当慢(必须在每条记录上执行Javascript代码),所以如果可以,请与索引查询结合使用.
db.T.find( { $where: function() { return this.Grade1 > this.Grade2 } } );
Run Code Online (Sandbox Code Playgroud)
或更紧凑:
db.T.find( { $where : "this.Grade1 > this.Grade2" } );
Run Code Online (Sandbox Code Playgroud)
您可以使用最近的答案中$expr描述的
chr*_*dam 37
如果您的查询仅包含$where运算符,则只能传入JavaScript表达式:
db.T.find("this.Grade1 > this.Grade2");
Run Code Online (Sandbox Code Playgroud)
为了获得更好的性能,请运行具有$redact管道的聚合操作,以过滤满足给定条件的文档.
该$redact管道包含了实现字段级别编辑的功能,$project并且$match它将返回与条件匹配的所有文档$$KEEP,并使用该$$PRUNE变量从管道结果中删除那些不匹配的文档.
运行以下聚合操作比使用$where大型集合更有效地过滤文档,因为它使用单个管道和本机MongoDB操作符,而不是使用JavaScript评估$where,这会降低查询速度:
db.T.aggregate([
{
"$redact": {
"$cond": [
{ "$gt": [ "$Grade1", "$Grade2" ] },
"$$KEEP",
"$$PRUNE"
]
}
}
])
Run Code Online (Sandbox Code Playgroud)
这是合并两个管道的更简化版本,$project并且$match:
db.T.aggregate([
{
"$project": {
"isGrade1Greater": { "$cmp": [ "$Grade1", "$Grade2" ] },
"Grade1": 1,
"Grade2": 1,
"OtherFields": 1,
...
}
},
{ "$match": { "isGrade1Greater": 1 } }
])
Run Code Online (Sandbox Code Playgroud)
使用MongoDB 3.4及更新版本:
db.T.aggregate([
{
"$addFields": {
"isGrade1Greater": { "$cmp": [ "$Grade1", "$Grade2" ] }
}
},
{ "$match": { "isGrade1Greater": 1 } }
])
Run Code Online (Sandbox Code Playgroud)
use*_*814 35
您可以使用$ expr(3.6 mongo版本运算符)在常规查询中使用聚合函数.
比较query operatorsVS aggregation comparison operators.
定期查询:
db.T.find({$expr:{$gt:["$Grade1", "$Grade2"]}})
Run Code Online (Sandbox Code Playgroud)
聚合查询:
db.T.aggregate({$match:{$expr:{$gt:["$Grade1", "$Grade2"]}}})
Run Code Online (Sandbox Code Playgroud)
Sin*_*ina 12
如果性能比可读性更重要,并且只要条件包含简单的算术运算,就可以使用聚合管道.首先,使用$ 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)
Run Code Online (Sandbox Code Playgroud)
使用聚合:
%timeit -n1 -r1 list(coll.aggregate([
{
'$project': {
'diff': {'$subtract': ['$Grade1', '$Grade2']},
'Grade1': 1,
'Grade2': 1
}
},
{
'$match': {'diff': {'$gt': 0}}
}
]))
Run Code Online (Sandbox Code Playgroud)
1个循环,每循环最佳1:192 ms
使用find和$ where:
%timeit -n1 -r1 list(coll.find({'$where': 'this.Grade1 > this.Grade2'}))
Run Code Online (Sandbox Code Playgroud)
1个循环,最佳1:每循环4.54秒