compare - 比较2个字段的MongoDb查询条件

我有一个集合T,有2个字段:Grade1Grade2,我想选择那些条件为Grade1 > Grade2,我怎样才能得到像MySQL这样的查询?

Select * from T Where Grade1 > Grade2
Diego Cheng asked 2019-09-11T10:59:45Z
4个解决方案
108 votes

你可以使用$ where。 请注意,它会相当慢(必须在每条记录上执行Javascript代码),所以如果可以,请与索引查询结合使用。

db.T.find( { $where: function() { return this.Grade1 > this.Grade2 } } );

或更紧凑:

db.T.find( { $where : "this.Grade1 > this.Grade2" } );

UPD for mongodb v.3.6 +

您可以使用最近的答案中描述的$expr

Ian answered 2019-09-11T11:00:22Z
33 votes

如果您的查询仅包含$match运算符,则只能传入JavaScript表达式:

db.T.find("this.Grade1 > this.Grade2");

为了获得更好的性能,请运行具有$match管道的聚合操作,以过滤满足给定条件的文档。

$match管道包含$match$match的功能以实现字段级别编辑,其中它将使用$match返回与条件匹配的所有文档,并从管道结果中删除使用$match变量不匹配的那些文档。


运行以下聚合操作比使用$match对大型集合更有效地过滤文档,因为它使用单个管道和本机MongoDB运算符,而不是使用$match的JavaScript评估,这可能会降低查询速度:

db.T.aggregate([
    {
        "$redact": {
            "$cond": [
                { "$gt": [ "$Grade1", "$Grade2" ] },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

这是合并两个管道$match$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 } }
])
chridam answered 2019-09-11T11:01:25Z
24 votes

您可以使用$ expr(3.6 mongo版本运算符)在常规查询中使用聚合函数。

比较aggregation comparison operators对比aggregation comparison operators

定期查询:

db.T.find({$expr:{$gt:["$Grade1", "$Grade2"]}})

聚合查询:

db.T.aggregate({$match:{$expr:{$gt:["$Grade1", "$Grade2"]}}})
Veeram answered 2019-09-11T11:02:15Z
11 votes

如果性能比可读性更重要,并且只要条件包含简单的算术运算,就可以使用聚合管道。 首先,使用$ 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

使用find和$ where:

%timeit -n1 -r1 list(coll.find({'$where': 'this.Grade1 > this.Grade2'}))

1个循环,最佳1:每循环4.54秒

Sina answered 2019-09-11T11:03:09Z
translate from https://stackoverflow.com:/questions/4442453/mongodb-query-condition-on-comparing-2-fields