$lookup (집계)
정의
호환성
다음 환경에서 호스팅되는 배포에 $lookup
사용할 수 있습니다.
MongoDB Atlas: 클라우드에서의 MongoDB 배포를 위한 완전 관리형 서비스
MongoDB Enterprise: MongoDB의 구독 기반 자체 관리 버전
MongoDB Community: MongoDB의 소스 사용 가능 무료 자체 관리 버전
구문
$lookup
단계의 구문은 다음과 같습니다.
단일 조인 조건으로 동일성 일치
입력 문서의 필드와 '조인된' 컬렉션의 문서 필드 간에 동등성 매치를 수행하려면 $lookup
단계는 다음과 같은 구문을 가집니다.
{ $lookup: { from: <collection to join>, localField: <field from the input documents>, foreignField: <field from the documents of the "from" collection>, as: <output array field> } }
$lookup
다음과 같은 필드가 있는 문서를 받습니다.
필드 | 설명 |
---|---|
조인을 수행할 동일한 데이터베이스 의 컬렉션 을 | |
입력 문서에 추가할 새 배열 필드의 이름을 지정합니다. 새 배열 필드에는 |
이 작업은 다음과 같은 유사 SQL 문장에 해당합니다.
SELECT *, ( SELECT ARRAY_AGG(*) FROM <collection to join> WHERE <foreignField> = <collection.localField> ) AS <output array field> FROM collection;
참고
이 페이지의 SQL 문은 MongoDB 집계 파이프라인 구문과 비교할 수 있도록 포함되어 있습니다. SQL 문을 실행할 수 없습니다.
MongoDB 예시는 이 페이지를 참조하세요.
조인된 컬렉션의 조인 조건 및 하위 쿼리
MongoDB는 다음을 지원합니다.
조인된 컬렉션에서 파이프라인 실행하기.
여러 조인 조건.
상관관계가 있는 하위 쿼리와 상관관계가 없는 하위 쿼리.
MongoDB에서 상관 관계 하위 쿼리는 조인된 컬렉션의 문서 필드를 참조하는 $lookup
단계의 파이프라인입니다. 상관 관계가 없는 하위 쿼리는 조인된 필드를 참조하지 않습니다.
참고
MongoDB 5.0부터는 $lookup
파이프라인 단계에서 $sample
단계, $sampleRate
연산자 또는 $rand
연산자를 포함하는 상관 관계가 없는 하위 쿼리의 경우, 반복 시 항상 하위 쿼리가 다시 실행됩니다. 이전에는 하위 쿼리 출력 크기에 따라 하위 쿼리 출력이 캐시되거나 하위 쿼리가 다시 실행되었습니다.
MongoDB 상관 서브쿼리는 내부 쿼리가 외부 쿼리 값을 참조하는 SQL 상관 서브쿼리와 유사합니다. SQL 비연관 서브쿼리는 외부 쿼리 값을 참조하지 않습니다.
MongoDB 5.0은 상관관계가 있는 간결한 하위 쿼리도 지원합니다.
두 컬렉션에 대해 상관 관계 및 비상관 관계 하위 쿼리를 수행하고 단일 동등성 매치 외에 다른 조인 조건을 수행하려면 이 $lookup
구문을 사용합니다.
{ $lookup: { from: <joined collection>, let: { <var_1>: <expression>, …, <var_n>: <expression> }, pipeline: [ <pipeline to run on joined collection> ], as: <output array field> } }
$lookup
단계에서는 다음과 같은 필드가 있는 문서를 수락합니다.
필드 | 설명 |
---|---|
조인 작업을 수행할 동일한 데이터베이스 의 컬렉션 을 지정합니다. 조인된 컬렉션 은 샤딩된 할 수 없습니다( 샤드 컬렉션 제한 참조). | |
선택 사항. 파이프라인 단계에서 사용할 변수를 지정합니다. 변수 표현식을 사용하여 에 입력되는 조인된 컬렉션 문서의 필드에 액세스 파이프라인 단계에서 변수를 참조하려면 let 변수는 에 중첩된 추가 단계를
| |
조인된 컬렉션에서 실행할
은 파이프라인 단계에서 변수를 참조하려면 let 변수는 에 중첩된 추가 단계를
| |
조인된 문서에 추가할 새 배열 필드의 이름을 지정합니다. 새 배열 필드에는 조인된 컬렉션에서 일치하는 문서가 포함됩니다. 지정한 이름이 조인된 문서에 이미 존재하는 경우 기존 필드를 덮어씁니다. |
이 작업은 다음과 같은 유사 SQL 문장에 해당합니다.
SELECT *, <output array field> FROM collection WHERE <output array field> IN ( SELECT <documents as determined from the pipeline> FROM <collection to join> WHERE <pipeline> );
다음 예시를 참조하세요.
간결한 구문을 사용한 상호 연관된 하위 쿼리
버전 5.0에 추가.
MongoDB 5.0부터는 상관관계가 있는 하위 쿼리에 간결한 구문을 사용할 수 있습니다. 연결된 하위 쿼리는 조인된 "외부" 컬렉션과 aggregate()
메서드가 실행된 "로컬" 컬렉션의 문서 필드를 참조합니다.
다음과 같은 새롭고 간결한 구문은 $expr
연산자 내부의 외부 및 로컬 필드에 대한 동등성 매치 요구 사항을 제거합니다.
{ $lookup: { from: <foreign collection>, localField: <field from local collection's documents>, foreignField: <field from foreign collection's documents>, let: { <var_1>: <expression>, …, <var_n>: <expression> }, pipeline: [ <pipeline to run> ], as: <output array field> } }
$lookup
은 다음과 같은 필드가 있는 문서를 수락합니다.
필드 | 설명 |
---|---|
로컬 컬렉션 에 조인할 동일한 데이터베이스 의 외부 컬렉션 을 지정합니다. 외부 컬렉션 은 샤딩된 할 수 없습니다(샤드 컬렉션 제한 참조). | |
외부 문서의 로컬 문서 에 | |
로컬 문서의 외부 문서 에 | |
선택 사항. 파이프라인 단계에서 사용할 변수를 지정합니다. 변수 표현식을 사용하여 에 입력되는 문서 필드에 액세스 파이프라인 단계에서 변수를 참조하려면 let 변수는 에 중첩된 추가 단계를
| |
외부 컬렉션에서 실행할
은(는) 파이프라인 단계에서 변수를 참조하려면 let 변수는 에 중첩된 추가 단계를
| |
외부 문서에 추가할 새 배열 필드의 이름을 지정합니다. 새 배열 필드에는 외부 컬렉션에서 일치하는 문서가 포함됩니다. 지정한 이름이 외부 문서에 이미 존재하는 경우 기존 필드를 덮어씁니다. |
이 작업은 다음과 같은 유사 SQL 문장에 해당합니다.
SELECT *, <output array field> FROM localCollection WHERE <output array field> IN ( SELECT <documents as determined from the pipeline> FROM <foreignCollection> WHERE <foreignCollection.foreignField> = <localCollection.localField> AND <pipeline match condition> );
이 예시를 참조하세요.
고려 사항
보기 및 데이터 정렬
$lookup
또는 $graphLookup
등 여러 뷰가 포함된 집계를 수행하는 경우 반드시 뷰의 데이터 정렬이 동일해야 합니다.
제한 사항
$lookup
단계에는 $out
단계나 $merge
단계를 포함할 수 없습니다. 즉, 조인(join)된 컬렉션에 대한 파이프라인을 지정할 때 pipeline
필드에 어느 단계도 포함할 수 없습니다.
{ $lookup: { from: <collection to join>, let: { <var_1>: <expression>, …, <var_n>: <expression> }, pipeline: [ <pipeline to execute on the joined collection> ], // Cannot include $out or $merge as: <output array field> } }
샤드 컬렉션 제한
$lookup
단계에서는 from
컬렉션을 샤딩 할 수 없습니다. 그러나 aggregate()
메서드를 실행하는 컬렉션은 샤딩할 수 있습니다. 이 예에서는 구체적으로 다음과 같습니다.
db.collection.aggregate([ { $lookup: { from: "fromCollection", ... } } ])
collection
을(를) 샤딩할 수 있습니다.fromCollection
는 샤딩할 수 없습니다.
샤드 컬렉션을 비샤드 컬렉션과 조인하려면 샤드 컬렉션에서 애그리게이션을 실행하고 비샤드 컬렉션을 조회합니다. 예를 들면 다음과 같습니다.
db.shardedCollection.aggregate([ { $lookup: { from: "unshardedCollection", ... } } ])
또는 여러 샤드 컬렉션을 조인하려면 다음을 고려하세요.
$lookup
애그리게이션 단계를 사용하는 대신 수동 조회를 수행하도록 클라이언트 애플리케이션을 수정합니다.가능하면 컬렉션을 조인할 필요가 없는 내장된 데이터 모델 을 사용합니다.
가능하면 Atlas Data Lake $lookup 파이프라인 단계를 사용하여 샤드 컬렉션을 조회합니다.
성능 고려 사항
$lookup
성능은 수행되는 작업 유형에 따라 달라집니다. 다양한 $lookup
작업에 대한 성능 고려 사항은 다음 표를 참조하세요.
$lookup 작업 | 성능 고려 사항 |
---|---|
| |
| |
|
일반적인 성능 전략은 인덱싱 전략 및 쿼리 최적화를 참조하세요.
중요
쿼리 내에서 $lookup
을 과도하게 사용하면 성능이 저하될 수 있습니다. 여러 $lookup
단계를 피하려면 쿼리 성능을 최적화하는 임베디드 데이터 모델을 고려하세요.
예시
단일 동일성 조인 수행하기 - $lookup
이 문서로 orders
컬렉션을 만듭니다.
db.orders.insertMany( [ { "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 }, { "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 }, { "_id" : 3 } ] )
이 문서로 다른 컬렉션 inventory
를 만듭니다.
db.inventory.insertMany( [ { "_id" : 1, "sku" : "almonds", "description": "product 1", "instock" : 120 }, { "_id" : 2, "sku" : "bread", "description": "product 2", "instock" : 80 }, { "_id" : 3, "sku" : "cashews", "description": "product 3", "instock" : 60 }, { "_id" : 4, "sku" : "pecans", "description": "product 4", "instock" : 70 }, { "_id" : 5, "sku": null, "description": "Incomplete" }, { "_id" : 6 } ] )
orders
컬렉션에 대한 다음 집계 작업은 orders
컬렉션의 item
필드와 inventory
컬렉션의 sku
필드를 사용하여 orders
문서를 inventory
컬렉션의 문서와 결합합니다.
db.orders.aggregate( [ { $lookup: { from: "inventory", localField: "item", foreignField: "sku", as: "inventory_docs" } } ] )
이 작업은 다음 문서를 반환합니다.
{ "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2, "inventory_docs" : [ { "_id" : 1, "sku" : "almonds", "description" : "product 1", "instock" : 120 } ] } { "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1, "inventory_docs" : [ { "_id" : 4, "sku" : "pecans", "description" : "product 4", "instock" : 70 } ] } { "_id" : 3, "inventory_docs" : [ { "_id" : 5, "sku" : null, "description" : "Incomplete" }, { "_id" : 6 } ] }
이 작업은 다음과 같은 유사 SQL 문장에 해당합니다.
SELECT *, inventory_docs FROM orders WHERE inventory_docs IN ( SELECT * FROM inventory WHERE sku = orders.item );
자세한 내용은 동등성 매치 성능 고려 사항을 참조하세요.
배열에 $lookup
사용
localField
가 배열인 경우 $unwind
단계 없이 스칼라 foreignField
에 일치시킬 수 있습니다.
예를 들어 다음 문서를 사용하여 예시 컬렉션 classes
를 만듭니다.
db.classes.insertMany( [ { _id: 1, title: "Reading is ...", enrollmentlist: [ "giraffe2", "pandabear", "artie" ], days: ["M", "W", "F"] }, { _id: 2, title: "But Writing ...", enrollmentlist: [ "giraffe1", "artie" ], days: ["T", "F"] } ] )
이 문서로 다른 컬렉션 members
를 만듭니다.
db.members.insertMany( [ { _id: 1, name: "artie", joined: new Date("2016-05-01"), status: "A" }, { _id: 2, name: "giraffe", joined: new Date("2017-05-01"), status: "D" }, { _id: 3, name: "giraffe1", joined: new Date("2017-10-01"), status: "A" }, { _id: 4, name: "panda", joined: new Date("2018-10-11"), status: "A" }, { _id: 5, name: "pandabear", joined: new Date("2018-12-01"), status: "A" }, { _id: 6, name: "giraffe2", joined: new Date("2018-12-01"), status: "D" } ] )
다음 집계 작업은 classes
컬렉션의 문서를 members
컬렉션과 결합하여 enrollmentlist
필드를 name
필드와 일치시킵니다.
db.classes.aggregate( [ { $lookup: { from: "members", localField: "enrollmentlist", foreignField: "name", as: "enrollee_info" } } ] )
이 연산은 다음을 반환합니다:
{ "_id" : 1, "title" : "Reading is ...", "enrollmentlist" : [ "giraffe2", "pandabear", "artie" ], "days" : [ "M", "W", "F" ], "enrollee_info" : [ { "_id" : 1, "name" : "artie", "joined" : ISODate("2016-05-01T00:00:00Z"), "status" : "A" }, { "_id" : 5, "name" : "pandabear", "joined" : ISODate("2018-12-01T00:00:00Z"), "status" : "A" }, { "_id" : 6, "name" : "giraffe2", "joined" : ISODate("2018-12-01T00:00:00Z"), "status" : "D" } ] } { "_id" : 2, "title" : "But Writing ...", "enrollmentlist" : [ "giraffe1", "artie" ], "days" : [ "T", "F" ], "enrollee_info" : [ { "_id" : 1, "name" : "artie", "joined" : ISODate("2016-05-01T00:00:00Z"), "status" : "A" }, { "_id" : 3, "name" : "giraffe1", "joined" : ISODate("2017-10-01T00:00:00Z"), "status" : "A" } ] }
$mergeObjects
과 함께 $lookup
사용
$mergeObjects
연산자는 여러 문서를 단일 문서로 결합합니다.
이 문서로 orders
컬렉션을 만듭니다.
db.orders.insertMany( [ { "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 }, { "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 } ] )
이 문서로 다른 컬렉션 items
를 만듭니다.
db.items.insertMany( [ { "_id" : 1, "item" : "almonds", description: "almond clusters", "instock" : 120 }, { "_id" : 2, "item" : "bread", description: "raisin and nut bread", "instock" : 80 }, { "_id" : 3, "item" : "pecans", description: "candied pecans", "instock" : 60 } ] )
다음 작업은 먼저 $lookup
단계를 사용하여 item
필드를 기준으로 두 컬렉션을 조인한 다음 $replaceRoot
에서 $mergeObjects
를 사용하여 items
와 orders
에서 조인된 문서를 병합합니다.
db.orders.aggregate( [ { $lookup: { from: "items", localField: "item", // field in the orders collection foreignField: "item", // field in the items collection as: "fromItems" } }, { $replaceRoot: { newRoot: { $mergeObjects: [ { $arrayElemAt: [ "$fromItems", 0 ] }, "$$ROOT" ] } } }, { $project: { fromItems: 0 } } ] )
이 작업은 다음 문서를 반환합니다.
{ _id: 1, item: 'almonds', description: 'almond clusters', instock: 120, price: 12, quantity: 2 }, { _id: 2, item: 'pecans', description: 'candied pecans', instock: 60, price: 20, quantity: 1 }
다중 조인 및 상관관계가 있는 하위 쿼리 수행하기 - $lookup
파이프라인은 조인된 컬렉션에서 실행할 수 있으며 여러 조인 조건을 포함할 수 있습니다.
조인 조건은 aggregate()
메서드가 실행된 로컬 컬렉션의 필드를 참조하고 조인된 컬렉션의 필드를 참조할 수 있습니다. 이렇게 하면 두 컬렉션 간에 상호 연관된 하위 쿼리가 가능합니다.
MongoDB 5.0은 상관관계가 있는 간결한 하위 쿼리를 지원합니다.
이 문서로 orders
컬렉션을 만듭니다.
db.orders.insertMany( [ { "_id" : 1, "item" : "almonds", "price" : 12, "ordered" : 2 }, { "_id" : 2, "item" : "pecans", "price" : 20, "ordered" : 1 }, { "_id" : 3, "item" : "cookies", "price" : 10, "ordered" : 60 } ] )
이 문서로 다른 컬렉션 warehouses
를 만듭니다.
db.warehouses.insertMany( [ { "_id" : 1, "stock_item" : "almonds", warehouse: "A", "instock" : 120 }, { "_id" : 2, "stock_item" : "pecans", warehouse: "A", "instock" : 80 }, { "_id" : 3, "stock_item" : "almonds", warehouse: "B", "instock" : 60 }, { "_id" : 4, "stock_item" : "cookies", warehouse: "B", "instock" : 40 }, { "_id" : 5, "stock_item" : "cookies", warehouse: "A", "instock" : 80 } ] )
다음 예제입니다.
orders.item
및warehouse.stock_item
필드에 대한 조인과 함께 상관된 하위 쿼리를 사용합니다.재고가 있는 품목의 수량이 주문한 수량을 충족할 수 있는지 확인합니다.
db.orders.aggregate( [ { $lookup: { from: "warehouses", let: { order_item: "$item", order_qty: "$ordered" }, pipeline: [ { $match: { $expr: { $and: [ { $eq: [ "$stock_item", "$$order_item" ] }, { $gte: [ "$instock", "$$order_qty" ] } ] } } }, { $project: { stock_item: 0, _id: 0 } } ], as: "stockdata" } } ] )
이 작업은 다음 문서를 반환합니다.
{ _id: 1, item: 'almonds', price: 12, ordered: 2, stockdata: [ { warehouse: 'A', instock: 120 }, { warehouse: 'B', instock: 60 } ] }, { _id: 2, item: 'pecans', price: 20, ordered: 1, stockdata: [ { warehouse: 'A', instock: 80 } ] }, { _id: 3, item: 'cookies', price: 10, ordered: 60, stockdata: [ { warehouse: 'A', instock: 80 } ] }
이 작업은 다음과 같은 유사 SQL 문장에 해당합니다.
SELECT *, stockdata FROM orders WHERE stockdata IN ( SELECT warehouse, instock FROM warehouses WHERE stock_item = orders.item AND instock >= orders.ordered );
$expr
연산자에 배치된 $eq
, $lt
, $lte
, $gt
, $gte
비교 연산자는 $lookup
단계에서 참조된 from
컬렉션의 인덱스를 사용할 수 있습니다. 제한 사항:
인덱스는 필드와 상수 간의 비교에만 사용할 수 있으므로
let
피연산자는 상수로 해결되어야 합니다.예를 들어
$a
및 상수 값 간의 비교에는 인덱스를 사용할 수 있지만,$a
및$b
간의 비교에는 인덱스를 사용할 수 없습니다.let
피연산자가 비어 있거나 누락된 값으로 확인되는 비교에는 인덱스가 사용되지 않습니다.다중 키 인덱스 는 사용되지 않습니다.
예를 들어 warehouses
컬렉션에 인덱스 { stock_item: 1, instock: 1 }
가 존재하는 경우입니다.
warehouses.stock_item
필드의 동등성 매치는 인덱스를 사용합니다.warehouses.instock
필드에 대한 쿼리의 범위 부분도 복합 인덱스의 인덱스 필드를 사용합니다.
상관관계가 없는 하위 쿼리 수행하기 - $lookup
집계 파이프라인 $lookup
단계는 조인된 컬렉션에서 파이프라인을 실행할 수 있으며, 이는 상호 관련되지 않은 하위 쿼리를 허용합니다. 상호 관련되지 않은 하위 쿼리는 조인된 문서 필드를 참조하지 않습니다.
참고
MongoDB 5.0부터는 $lookup
파이프라인 단계에서 $sample
단계, $sampleRate
연산자 또는 $rand
연산자를 포함하는 상관 관계가 없는 하위 쿼리의 경우, 반복 시 항상 하위 쿼리가 다시 실행됩니다. 이전에는 하위 쿼리 출력 크기에 따라 하위 쿼리 출력이 캐시되거나 하위 쿼리가 다시 실행되었습니다.
이 문서로 absences
컬렉션을 만듭니다.
db.absences.insertMany( [ { "_id" : 1, "student" : "Ann Aardvark", sickdays: [ new Date ("2018-05-01"),new Date ("2018-08-23") ] }, { "_id" : 2, "student" : "Zoe Zebra", sickdays: [ new Date ("2018-02-01"),new Date ("2018-05-23") ] }, ] )
이 문서로 다른 컬렉션 holidays
를 만듭니다.
db.holidays.insertMany( [ { "_id" : 1, year: 2018, name: "New Years", date: new Date("2018-01-01") }, { "_id" : 2, year: 2018, name: "Pi Day", date: new Date("2018-03-14") }, { "_id" : 3, year: 2018, name: "Ice Cream Day", date: new Date("2018-07-15") }, { "_id" : 4, year: 2017, name: "New Years", date: new Date("2017-01-01") }, { "_id" : 5, year: 2017, name: "Ice Cream Day", date: new Date("2017-07-16") } ] )
다음 작업은 holidays
컬렉션의 2018년 공휴일 정보와 함께 absences
컬렉션을 조인합니다.
db.absences.aggregate( [ { $lookup: { from: "holidays", pipeline: [ { $match: { year: 2018 } }, { $project: { _id: 0, date: { name: "$name", date: "$date" } } }, { $replaceRoot: { newRoot: "$date" } } ], as: "holidays" } } ] )
이 연산은 다음을 반환합니다:
{ _id: 1, student: 'Ann Aardvark', sickdays: [ ISODate("2018-05-01T00:00:00.000Z"), ISODate("2018-08-23T00:00:00.000Z") ], holidays: [ { name: 'New Years', date: ISODate("2018-01-01T00:00:00.000Z") }, { name: 'Pi Day', date: ISODate("2018-03-14T00:00:00.000Z") }, { name: 'Ice Cream Day', date: ISODate("2018-07-15T00:00:00.000Z") } ] }, { _id: 2, student: 'Zoe Zebra', sickdays: [ ISODate("2018-02-01T00:00:00.000Z"), ISODate("2018-05-23T00:00:00.000Z") ], holidays: [ { name: 'New Years', date: ISODate("2018-01-01T00:00:00.000Z") }, { name: 'Pi Day', date: ISODate("2018-03-14T00:00:00.000Z") }, { name: 'Ice Cream Day', date: ISODate("2018-07-15T00:00:00.000Z") } ] }
이 작업은 다음과 같은 유사 SQL 문장에 해당합니다.
SELECT *, holidays FROM absences WHERE holidays IN ( SELECT name, date FROM holidays WHERE year = 2018 );
자세한 내용은 상관관계가 없는 하위 쿼리 성능 고려 사항을참조하세요.
상관관계가 있는 간결한 하위 쿼리 수행하기 - $lookup
버전 5.0에 추가.
MongoDB 5.0부터 집계 파이프라인 $lookup
단계는 컬렉션 간의 조인을 개선하는 간결한 상관관계 하위 쿼리 구문을 지원합니다. 새로운 간결한 구문은 $match
단계에서 $expr
연산자 내부의 외부 및 로컬 필드에 대한 동등성 매치 요구 사항을 제거합니다.
컬렉션 restaurants
을 만듭니다:
db.restaurants.insertMany( [ { _id: 1, name: "American Steak House", food: [ "filet", "sirloin" ], beverages: [ "beer", "wine" ] }, { _id: 2, name: "Honest John Pizza", food: [ "cheese pizza", "pepperoni pizza" ], beverages: [ "soda" ] } ] )
음식 및 음료 주문(선택 사항)이 포함된 다른 컬렉션 orders
를 만듭니다.
db.orders.insertMany( [ { _id: 1, item: "filet", restaurant_name: "American Steak House" }, { _id: 2, item: "cheese pizza", restaurant_name: "Honest John Pizza", drink: "lemonade" }, { _id: 3, item: "cheese pizza", restaurant_name: "Honest John Pizza", drink: "soda" } ] )
다음 예제입니다.
orders.restaurant_name
localField를restaurants.name
foreignField와 매칭시켜orders
와restaurants
컬렉션을 조인합니다.pipeline
이 실행되기 전에 매치가 수행됩니다.각각
$$orders_drink
및$beverages
를 사용하여 액세스하는orders.drink
및restaurants.beverages
필드 간에$in
배열 일치를 수행합니다.
db.orders.aggregate( [ { $lookup: { from: "restaurants", localField: "restaurant_name", foreignField: "name", let: { orders_drink: "$drink" }, pipeline: [ { $match: { $expr: { $in: [ "$$orders_drink", "$beverages" ] } } } ], as: "matches" } } ] )
orders.drink
및 restaurants.beverages
필드에 soda
값과 일치하는 항목이 있습니다. 이 출력은 matches
배열을 표시하고 일치 항목에 대해 restaurants
컬렉션의 조인된 모든 필드를 포함합니다.
{ "_id" : 1, "item" : "filet", "restaurant_name" : "American Steak House", "matches" : [ ] } { "_id" : 2, "item" : "cheese pizza", "restaurant_name" : "Honest John Pizza", "drink" : "lemonade", "matches" : [ ] } { "_id" : 3, "item" : "cheese pizza", "restaurant_name" : "Honest John Pizza", "drink" : "soda", "matches" : [ { "_id" : 2, "name" : "Honest John Pizza", "food" : [ "cheese pizza", "pepperoni pizza" ], "beverages" : [ "soda" ] } ] }
상관관계가 있는 간결한 하위 쿼리가 소개되기 전에는 $lookup
를 통한 다중 조인 및 상관 하위 쿼리 수행에서 보여진 것처럼 pipeline
$lookup
단계에서 $expr
연산자를 활용해 로컬 필드와 조인 필드 사이에서$eq
동등성 매치를 사용해야 했습니다.
이 예에서는 5.0 이전 버전의 구형 MongoDB 구문을 사용하며 버전에서 앞의 간결한 예와 동일한 결과를 반환합니다.
db.orders.aggregate( [ { $lookup: { from: "restaurants", let: { orders_restaurant_name: "$restaurant_name", orders_drink: "$drink" }, pipeline: [ { $match: { $expr: { $and: [ { $eq: [ "$$orders_restaurant_name", "$name" ] }, { $in: [ "$$orders_drink", "$beverages" ] } ] } } } ], as: "matches" } } ] )
이전 예시는 다음 유사 SQL 문에 해당합니다.
SELECT *, matches FROM orders WHERE matches IN ( SELECT * FROM restaurants WHERE restaurants.name = orders.restaurant_name AND restaurants.beverages = orders.drink );
자세한 내용은 상관관계가 있는 하위 쿼리 성능 고려 사항을 참조하세요.