programing

두 필드 비교 시 MongoDb 쿼리 조건

bestprogram 2023. 4. 2. 12:00

두 필드 비교 시 MongoDb 쿼리 조건

컬렉션이 있습니다.T, 2개의 필드가 있습니다.Grade1그리고.Grade2조건이 있는 것을 선택하고 싶다.Grade1 > Grade2MySQL과 같은 쿼리를 받으려면 어떻게 해야 하나요?

Select * from T Where Grade1 > Grade2

$를 사용할 수 있습니다.(모든 레코드에서 Javascript 코드를 실행해야 함) 상당히 느리므로 가능하면 인덱스된 쿼리와 결합할 수 있습니다.

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

콤팩트 이상:

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

mongodb v.3.6+용 UPD

사용할 수 있습니다.$expr최근의 회답에서 기술한 바와 같이

$expr(3.6 mongo 버전 연산자)을 사용하여 일반 쿼리에서 집약 함수를 사용할 수 있습니다.

와 비교합니다.

정기 쿼리:

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

집약 쿼리:

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

쿼리가 연산자로만 구성되어 있는 경우 JavaScript 식만 전달할 수 있습니다.

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

성능을 향상시키려면 지정된 조건을 충족하는 문서를 필터링하는 파이프라인이 있는 집계 작업을 실행하십시오.

파이프라인은 필드 수준 수정 및 필드 수준 수정의 기능을 통합하며, 여기서 필드 수준 수정은 를 사용하여 조건에 일치하는 모든 문서를 반환하고 파이프라인 결과에서 변수를 사용하여 일치하지 않는 문서를 제거합니다.


다음 집약 조작 필터를 실행하면 대규모 컬렉션에 사용하는 것보다 문서를 효율적으로 실행할 수 있습니다.이 필터에서는 에서 JavaScript 평가를 사용하는 것이 아니라 단일 파이프라인 및 네이티브 MongoDB 연산자를 사용하기 때문에 쿼리가 느려질 수 있습니다.

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

2개의 파이프라인을 통합한 보다 간단한 버전입니다.

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밀리초/루프

찾기 및 $where 사용:

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

1루프, 1루프당 베스트: 4.54초

언급URL : https://stackoverflow.com/questions/4442453/mongodb-query-condition-on-comparing-2-fields