$expr
정의
버전 5.0에서 변경됨
$expr
쿼리 언어 내에서 집계 표현식을 사용할 수 있습니다.
호환성
다음 환경에서 호스팅되는 배포에 $expr
사용할 수 있습니다.
MongoDB Atlas: 클라우드에서의 MongoDB 배포를 위한 완전 관리형 서비스
MongoDB Enterprise: MongoDB의 구독 기반 자체 관리 버전
MongoDB Community: MongoDB의 소스 사용 가능 무료 자체 관리 버전
구문
$expr
의 구문은 다음과 같습니다:
{ $expr: { <expression> } }
인수는 유효한 모든 애그리게이션 표현식 일 수 있습니다. 자세한 내용은 표현식을 참조하세요.
행동
$expr
은 $match
단계에서 동일한 문서의 필드를 비교하는 쿼리 표현식을 작성할 수 있습니다.
$match
단계가 $lookup
단계의 일부인 경우 $expr
(은)는 let
변수를 사용하여 필드를 비교할 수 있습니다. 예시는 다중 합류 수행 및 $lookup
을(를)사용한 상관 하위 쿼리를 참조하세요.
$expr
연산자에 배치된 $eq
, $lt
, $lte
, $gt
및 $gte
비교 연산자는 $lookup
단계에서 참조된 from
컬렉션의 인덱스를 사용할 수 있습니다. 제한 사항:
인덱스는 필드와 상수 간의 비교에만 사용할 수 있으므로
let
피연산자는 상수로 해결되어야 합니다.예를 들어
$a
및 상수 값 간의 비교에는 인덱스를 사용할 수 있지만,$a
및$b
간의 비교에는 인덱스를 사용할 수 없습니다.let
피연산자가 비어 있거나 누락된 값으로 확인되는 비교에는 인덱스가 사용되지 않습니다.다중 키 인덱스 는 사용되지 않습니다.
예시
단일 문서에서 두 필드 비교
다음 문서가 포함된 monthlyBudget
collection을 생각해 보세요.
db.monthlyBudget.insertMany( [ { _id : 1, category : "food", budget : 400, spent : 450 }, { _id : 2, category : "drinks", budget : 100, spent : 150 }, { _id : 3, category : "clothes", budget : 100, spent : 50 }, { _id : 4, category : "misc", budget : 500, spent : 300 }, { _id : 5, category : "travel", budget : 200, spent : 650 } ] )
다음 작업은 $expr
을 사용하여 spent
가 budget
을 초과하는 문서를 찾습니다.
db.monthlyBudget.find( { $expr: { $gt: [ $spent , $budget ] } } )
이 연산은 다음과 같은 결과를 반환합니다.
{ _id : 1, category : "food", budget : 400, spent : 450 } { _id : 2, category : "drinks", budget : 100, spent : 150 } { _id : 5, category : "travel", budget : 200, spent : 650 }
$expr
조건문과 함께 사용
일부 쿼리에는 쿼리 필터를 정의할 때 조건부 논리를 실행하는 기능이 필요합니다. 집계 파이프라인은 조건문을 표현하는 $cond
연산자를 제공합니다. $expr
연산자를 $cond
연산자와 함께 사용하면 쿼리에 조건부 필터를 지정할 수 있습니다.
다음 문서로 샘플 supplies
컬렉션을 생성합니다.
db.supplies.insertMany( [ { _id : 1, item : "binder", qty : NumberInt("100"), price : NumberDecimal("12") }, { _id : 2, item : "notebook", qty : NumberInt("200"), price : NumberDecimal("8") }, { _id : 3, item : "pencil", qty : NumberInt("50"), price : NumberDecimal("6") }, { _id : 4, item : "eraser", qty : NumberInt("150"), price : NumberDecimal("3") }, { _id : 5, item : "legal pad", qty : NumberInt("42"), price : NumberDecimal("10") } ] )
다음 달에 예정된 판매에 대해 다음과 같이 가격을 할인하려고 한다고 가정합니다.
qty
이(가) 100보다 크거나 같으면 할인된 가격은price
의 0.5가 됩니다.qty
이(가) 100보다 작은 경우 할인된 가격은price
의 0.75가 됩니다.
할인을 적용하기 전에 supplies
collection에서 할인된 가격이 미만인 품목이 무엇인지 알고 5
싶습니다.
다음 예시는 $cond
와 함께 $expr
을 사용해 qty
및 $lt
를 기반으로 할인된 가격을 계산하여 계산된 할인 가격이 NumberDecimal("5")
보다 작은 문서를 반환합니다.
// Aggregation expression to calculate discounted price let discountedPrice = { $cond: { if: { $gte: ["$qty", 100] }, then: { $multiply: ["$price", NumberDecimal("0.50")] }, else: { $multiply: ["$price", NumberDecimal("0.75")] } } }; // Query the supplies collection using the aggregation expression db.supplies.find( { $expr: { $lt:[ discountedPrice, NumberDecimal("5") ] } });
다음 표에는 각 문서의 할인가와 할인된 가격이 NumberDecimal("5")
미만인지 여부가 나와 있습니다 (즉, 문서가 쿼리 조건을 충족하는지 여부).
문서 | 할인 가격 | < NumberDecimal("5") |
---|---|---|
{"_id": 1, "item": "binder", "qty": 100, "price": NumberDecimal("12") } | NumberDecimal("6.00") | false |
{"_id": 2, "item": "notebook", "qty": 200, "price": NumberDecimal("8") } | NumberDecimal("4.00") | true |
{"_id": 3, "item": "pencil", "qty": 50, "price": NumberDecimal("6") } | NumberDecimal("4.50") | true |
{"_id": 4, "item": "eraser", "qty": 150, "price": NumberDecimal("3") } | NumberDecimal("1.50") | true |
{"_id": 5, "item": "legal pad", "qty": 42, "price": NumberDecimal("10") } | NumberDecimal("7.50") | false |
db.collection.find()
작업은 계산된 할인 가격이 NumberDecimal("5")
미만인 문서를 반환합니다.
{ _id : 2, item : "notebook", qty : 200 , price : NumberDecimal("8") } { _id : 3, item : "pencil", qty : 50 , price : NumberDecimal("6") } { _id : 4, item : "eraser", qty : 150 , price : NumberDecimal("3") }
$cond
에서 유효 할인 가격을 계산하더라도 반품된 문서에는 해당 가격이 반영되지 않습니다. 대신 반환된 문서는 원래 상태의 일치하는 문서를 나타냅니다. 할인된 가격이 5
보다 컸기 때문에 찾기 작업을 수행해도 binder
또는 legal pad
문서가 반환되지 않았습니다.