조회수
MongoDB 뷰는 다른 컬렉션 또는 뷰의 집계 파이프라인 에 의해 콘텐츠가 정의되는 쿼리 가능 객체 입니다. MongoDB 는 뷰 콘텐츠를 디스크에 유지하지 않습니다. 뷰의 콘텐츠는 클라이언트 가 뷰를 쿼리할 때 온디맨드 으로 계산됩니다. MongoDB 는 클라이언트에게 뷰를 쿼리 할 수 있는 권한을 요구할 수 있습니다. MongoDB 는 뷰에 대한 쓰기 (write) 작업을 지원 하지 않습니다.
예를 들어 다음과 같은 작업을 수행할 수 있습니다.
exclude
개인 또는 개인 정보 (PII) 에 대한 직원 데이터 컬렉션에 대한 뷰를 만듭니다. 애플리케이션은 PII가 포함되지 않은 직원 데이터에 대한 보기를 쿼리할 수 있습니다.add
계산된 필드 및 메트릭에 수집된 센서 데이터 컬렉션에 대한 보기를 만듭니다. Applications can use simple find operations to query the data.joins
각각 재고와 주문 내역을 포함하는 두 개의 컬렉션을 생성하는 뷰를 생성합니다. 애플리케이션은 복잡한 기본 파이프라인을 관리하거나 이해하지 않고도 조인된 데이터를 쿼리할 수 있습니다.
MongoDB Atlas에서 호스팅되는 배포를 위해 UI에서 구체화된 뷰를 생성 할 수 있습니다.
클라이언트 가 뷰를 쿼리 하면 MongoDB 는 클라이언트 쿼리 를 기본 파이프라인 에 추가하고 결합된 파이프라인 의 결과를 클라이언트 에 반환합니다. MongoDB 는 결합된 파이프라인 에 집계 파이프라인 최적화 를 적용 할 수 있습니다.
참고
다음 페이지에서는 뷰에 대해 설명합니다. 온디맨드 구체화된 뷰에 대한 설명은 온 디맨드 구체화된 뷰를 참조하세요.
뷰 만들기
뷰를 생성하거나 정의하려면 다음을 수행합니다.
db.createCollection()
메서드 또는create
명령을 사용합니다.db.createCollection( "<viewName>", { "viewOn" : "<source>", "pipeline" : [<pipeline>], "collation" : { <collation> } } ) db.createView()
메서드를 사용합니다:db.createView( "<viewName>", "<source>", [<pipeline>], { "collation" : { <collation> } } )
참고
- 소스 collection과 동일한 데이터베이스에 뷰를 생성해야 합니다.
경고
MongoDB Server가 충돌하므로 system.profile
이라는 이름의 time series 컬렉션 또는 뷰를 만들려고 시도하지 마세요.
행동
뷰는 다음과 같은 동작을 나타냅니다.
읽기 전용
뷰는 읽기 전용입니다. 뷰에 대한 쓰기 작업에 오류가 발생합니다.
뷰를 지원할 수 있는 읽기 작업은 다음과 같습니다.
인덱스 사용 및 정렬 작업
뷰는 기본 collection의 인덱스를 사용합니다.
인덱스는 기본 collection에 있으므로 뷰에서 직접 인덱스를 생성, 삭제 또는 다시 작성할 수 없으며 뷰에서 인덱스 목록을 가져올 수 없습니다.
MongoDB 4.4부터는 뷰에서
$natural
find
명령을 실행할 때 정렬을 지정할 수 있습니다. 이전 버전의 MongoDB는 뷰에서$natural
정렬을 지원하지 않습니다.뷰의 기본 집계 파이프라인에는 블로킹 정렬 및 블로킹 그룹 작업에 대한 100메가바이트 메모리 제한이 적용됩니다. MongoDB 4.4부터는 뷰에서
allowDiskUse: true
와 함께find
명령을 실행하여 MongoDB가 임시 파일을 사용하여 정렬 및 그룹 작업을 차단하도록 허용할 수 있습니다.MongoDB 4.4 이전에는
aggregate
명령만allowDiskUse
옵션을 허용했습니다.
프로젝션 제한 사항
변경할 수 없는 이름
뷰의 이름은 바꿀 수 없습니다.
뷰 생성
뷰는 읽기 작업 중에 온디맨드로 계산되며, MongoDB는 기본 집계 파이프라인의 일부로 뷰에 대한 읽기 작업을 실행합니다. 따라서 뷰는 다음과 같은 작업을 지원하지 않습니다.
뷰를 만드는 데 사용된 집계 파이프라인이
_id
필드를 억제하는 경우 뷰의 문서에_id
필드가 없습니다.
뷰를 쿼리하면 다음이 수행됩니다.
db.collection.find()
에 대한 쿼리filter
,projection
,sort
,skip
,limit
및 기타 작업은 해당 집계 파이프라인 단계로변환됩니다.변환된 집계 파이프라인 단계는 뷰의 집계 파이프라인 끝에 추가됩니다. 이는 뷰를 생성할 때 설정된 뷰의 기본 파이프라인을 수정하지 않습니다.
집계 파이프라인 옵티마이저는 성능을 개선하기 위해 뷰 집계 파이프라인 단계를 재구성합니다. 이는 쿼리 결과를 변경하지 않습니다.
샤드 뷰
뷰의 기본 collection이 샤드된 경우 뷰도 샤드된 것으로 간주됩니다. 따라서 $lookup
및 $graphLookup
연산의 from
필드에 대해 샤드 뷰를 지정할 수 없습니다.
보기 및 데이터 정렬
뷰를 만들 때 뷰의 기본 데이터 정렬을 지정할 수 있습니다. 데이터 정렬이 지정되지 않은 경우, 뷰의 기본 데이터 정렬은 "simple" 이진 비교 데이터 정렬기입니다. 즉, 뷰는 컬렉션의 기본 데이터 정렬을 상속하지 않습니다.
뷰의 문자열 비교에서는 뷰의 기본 데이터 정렬을 사용합니다. 뷰의 기본 데이터 정렬을 변경하거나 재정의하려는 작업은 오류를 반환하며 실패합니다.
다른 보기에서 보기를 만드는 경우 원본 보기의 데이터 정렬과 다른 데이터 정렬을 지정할 수 없습니다.
$lookup
또는$graphLookup
과 같이 여러 뷰를 포함하는 집계를 수행하는 경우 뷰의 데이터 정렬이 동일해야 합니다.
스냅샷 격리
보기는 컬렉션 변경 사항의 타임스탬프를 유지하지 않으며 특정 시점 또는 스냅샷 읽기 격리를 지원하지 않습니다.
퍼블릭 뷰 정의
db.getCollectionInfos()
및 db.getCollectionNames()
와 같이 collection을 나열하는 작업은 출력에 뷰를 포함합니다.
중요
뷰 정의는 공개입니다. 즉, 뷰에 대한 db.getCollectionInfos()
및 explain
작업에는 뷰를 정의하는 파이프라인이 포함됩니다. 따라서 뷰 정의에 민감한 필드와 값을 직접 참조하지 않는 것이 좋습니다.
뷰 제거
뷰를 제거하려면 뷰에서 db.collection.drop()
메서드를 사용합니다.
뷰 수정
뷰를 삭제하고 다시 만들거나 collMod
명령을 사용하여 뷰를 수정할 수 있습니다.
지원되는 작업
다음 작업은 이 페이지에 언급된 제한 사항을 제외하고 뷰에 대한 지원을 제공합니다.
명령. | 방법 |
---|---|
예시
다음 예시에서 사용할 students
컬렉션을 만듭니다.
db.students.insertMany( [ { sID: 22001, name: "Alex", year: 1, score: 4.0 }, { sID: 21001, name: "bernie", year: 2, score: 3.7 }, { sID: 20010, name: "Chris", year: 3, score: 2.5 }, { sID: 22021, name: "Drew", year: 1, score: 3.2 }, { sID: 17301, name: "harley", year: 6, score: 3.1 }, { sID: 21022, name: "Farmer", year: 1, score: 2.2 }, { sID: 20020, name: "george", year: 3, score: 2.8 }, { sID: 18020, name: "Harley", year: 5, score: 2.8 }, ] )
db.createView()를 사용하여 뷰 만들기
db.createView()
를 사용하여 1학년 학생으로 제한되는 뷰를 만듭니다.
db.createView( "firstYears", "students", [ { $match: { year: 1 } } ] )
예시:
firstYears
새 뷰의 이름입니다.students
뷰의 기반이 되는 컬렉션입니다.$match
는students
컬렉션의 1학년 학생과 일치하는 집계 표현식입니다.
이 예에서는 뷰를 쿼리합니다.
db.firstYears.find({}, { _id: 0 } )
다음 출력에는 1학년 학생에 대한 데이터가 있는 문서만 포함되어 있습니다. { _id: 0 }
프로젝션은 출력 디스플레이에 _id
필드를 표시하지 않습니다.
[ { sID: 22001, name: 'Alex', year: 1, score: 4 }, { sID: 22021, name: 'Drew', year: 1, score: 3.2 }, { sID: 21022, name: 'Farmer', year: 1, score: 2.2 } ]
db.createCollection()을 사용하여 뷰 만들기
db.createCollection()
메서드를 사용하면 특정 옵션이 있는 컬렉션 또는 뷰를 만들 수 있습니다.
다음 예에서는 graduateStudents
뷰를 만듭니다. 뷰에는 $match
단계에서 선택한 문서만 포함되어 있습니다. 선택적 데이터 정렬 설정에 따라 정렬 순서가 결정됩니다.
db.createCollection( "graduateStudents", { viewOn: "students", pipeline: [ { $match: { $expr: { $gt: [ "$year", 4 ] } } } ], collation: { locale: "en", caseFirst: "upper" } } )
다음 예시에서는 보기를 쿼리합니다. $unset
단계에서는 명확성을 위해 출력에서 _id
필드를 제거합니다.
db.graduateStudents.aggregate( [ { $sort: { name: 1 } }, { $unset: [ "_id" ] } ] )
출력이 정렬될 때 $sort
단계에서는 데이터 정렬 순서를 사용하여 대문자를 소문자보다 먼저 정렬합니다.
[ { sID: 18020, name: 'Harley', year: 5, score: 2.8 }, { sID: 17301, name: 'harley', year: 6, score: 3.1 } ]
뷰를 사용하여 두 컬렉션에 참여
$lookup
를 사용하여 두 collection에 대한 뷰를 만든 다음 해당 뷰에 대해 쿼리를 실행하는 것이 편리한 경우가 많습니다. 애플리케이션은 복잡한 파이프라인을 구성하거나 유지 관리할 필요 없이 뷰를 쿼리할 수 있습니다.
두 개의 샘플 컬렉션 inventory
및 orders
를 만듭니다.
db.inventory.insertMany( [ { prodId: 100, price: 20, quantity: 125 }, { prodId: 101, price: 10, quantity: 234 }, { prodId: 102, price: 15, quantity: 432 }, { prodId: 103, price: 17, quantity: 320 } ] ) db.orders.insertMany( [ { orderID: 201, custid: 301, prodId: 100, numPurchased: 20 }, { orderID: 202, custid: 302, prodId: 101, numPurchased: 10 }, { orderID: 203, custid: 303, prodId: 102, numPurchased: 5 }, { orderID: 204, custid: 303, prodId: 103, numPurchased: 15 }, { orderID: 205, custid: 303, prodId: 103, numPurchased: 20 }, { orderID: 206, custid: 302, prodId: 102, numPurchased: 1 }, { orderID: 207, custid: 302, prodId: 101, numPurchased: 5 }, { orderID: 208, custid: 301, prodId: 100, numPurchased: 10 }, { orderID: 209, custid: 303, prodId: 103, numPurchased: 30 } ] )
각 collection의 요소를 결합하는 뷰를 만듭니다.
db.createView( "sales", "orders", [ { $lookup: { from: "inventory", localField: "prodId", foreignField: "prodId", as: "inventoryDocs" } }, { $project: { _id: 0, prodId: 1, orderId: 1, numPurchased: 1, price: "$inventoryDocs.price" } }, { $unwind: "$price" } ] )
예시:
db.createView()
는sales
뷰를 만듭니다.sales
뷰는orders
collection을 기반으로 합니다.$lookup
단계에서는orders
컬렉션의prodId
필드를 사용하여inventory
컬렉션에서 일치하는prodId
필드를 가진 문서를 조인합니다.일치하는 문서는
inventoryDocs
필드에 배열로 추가됩니다.$project
단계에서는 사용 가능한 필드의 하위 집합을 선택합니다.$unwind
단계는price
필드를 배열에서 스칼라 값으로 변환합니다.
sales
보기의 문서는 다음과 같습니다.
{ prodId: 100, numPurchased: 20, price: 20 }, { prodId: 101, numPurchased: 10, price: 10 }, { prodId: 102, numPurchased: 5, price: 15 }, { prodId: 103, numPurchased: 15, price: 17 }, { prodId: 103, numPurchased: 20, price: 17 }, { prodId: 102, numPurchased: 1, price: 15 }, { prodId: 101, numPurchased: 5, price: 10 }, { prodId: 100, numPurchased: 10, price: 20 }, { prodId: 103, numPurchased: 30, price: 17 }
각 제품의 총 판매액을 찾으려면 뷰를 쿼리합니다.
db.sales.aggregate( [ { $group: { _id: "$prodId", amountSold: { $sum: { $multiply: [ "$price", "$numPurchased" ] } } } } ] )
출력은 다음과 같습니다:
[ { _id: 100, amountSold: 600 }, { _id: 103, amountSold: 1105 }, { _id: 101, amountSold: 150 }, { _id: 102, amountSold: 90 } ]