정의
버전 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") |
|
{"_id": 2, "item": "notebook", "qty": 200, "price": NumberDecimal("8") } | NumberDecimal("4.00") |
|
{"_id": 3, "item": "pencil", "qty": 50, "price": NumberDecimal("6") } | NumberDecimal("4.50") |
|
{"_id": 4, "item": "eraser", "qty": 150, "price": NumberDecimal("3") } | NumberDecimal("1.50") |
|
{"_id": 5, "item": "legal pad", "qty": 42, "price": NumberDecimal("10") } | NumberDecimal("7.50") |
|
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 문서가 반환되지 않았습니다.