문서 메뉴

문서 홈애플리케이션 개발MongoDB 매뉴얼

조회수

이 페이지의 내용

  • 뷰 만들기
  • 행동
  • 뷰 삭제
  • 뷰 수정
  • 지원되는 작업
  • 예제

MongoDB 뷰는 다른 컬렉션 또는 뷰의 집계 파이프라인 에 의해 콘텐츠가 정의되는 쿼리 가능한 객체입니다. MongoDB는 뷰 콘텐츠를 디스크에 유지하지 않습니다. 뷰의 콘텐츠는 클라이언트 가 뷰를쿼리 할 때 온디맨드 방식으로 계산됩니다. MongoDB는 클라이언트에게 뷰를 쿼리할 수 있는 권한 을 요구할 수 있습니다. MongoDB는 뷰에 대한 쓰기 작업을 지원하지 않습니다.

예를 들어 다음과 같은 작업을 수행할 수 있습니다.

클라이언트 가 뷰를 쿼리하면 MongoDB는 클라이언트 쿼리를 기본 파이프라인에 추가하고 결합된 파이프라인의 결과를 클라이언트에 반환합니다. MongoDB는 결합된 파이프라인에 집계 파이프라인 최적화 를 적용할 수 있습니다.

참고

다음 페이지에서는 뷰에 대해 설명합니다. 온디맨드 구체화된 뷰에 대한 설명은 디맨드 구체화된 뷰를 참조하세요.

뷰를 생성하거나 정의하려면 다음을 수행합니다.

  • db.createCollection() 메서드 또는 create 명령을 사용합니다.

    db.createCollection(
    "<viewName>",
    {
    "viewOn" : "<source>",
    "pipeline" : [<pipeline>],
    "collation" : { <collation> }
    }
    )
  • db.createView() 메서드를 사용합니다:

    db.createView(
    "<viewName>",
    "<source>",
    [<pipeline>],
    {
    "collation" : { <collation> }
    }
    )

참고

- 소스 collection과 동일한 데이터베이스에 뷰를 생성해야 합니다.

  • 뷰 정의 pipeline 에는 $out 또는 $merge 단계를 포함할 수 없습니다. 뷰 정의에 중첩된 파이프라인이 포함된 경우(예: 뷰 정의에 $lookup 또는 $facet 단계가 포함된 경우) 이 제한은 중첩된 파이프라인에도 적용됩니다.

경고

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 옵션을 허용했습니다.

    다음도 참조하세요.

    블로킹 정렬 작업 메모리 제한에 대한 자세한 내용은 정렬 작업을 참조하세요.

뷰에 대한 find() 작업은 다음 프로젝션 연산자를 지원하지 않습니다.

의 이름은 바꿀 수 없습니다.

  • 뷰는 읽기 작업 중에 온디맨드로 계산되며, MongoDB는 기본 집계 파이프라인의 일부로 뷰에 대한 읽기 작업을 실행합니다. 따라서 뷰는 다음과 같은 작업을 지원하지 않습니다.

  • 뷰를 만드는 데 사용된 집계 파이프라인이 _id 필드를 억제하는 경우 뷰의 문서에 _id 필드가 없습니다.

뷰를 쿼리하면 다음이 수행됩니다.

뷰의 기본 collection이 샤드된 경우 뷰도 샤드된 것으로 간주됩니다. 따라서 $lookup$graphLookup 연산의 from 필드에 대해 샤드 뷰를 지정할 수 없습니다.

  • 뷰를 만들 때 뷰의 기본 데이터 정렬을 지정할 수 있습니다. 데이터 정렬이 지정되지 않은 경우, 뷰의 기본 데이터 정렬은 "simple" 이진 비교 데이터 정렬기입니다. 즉, 뷰는 컬렉션의 기본 데이터 정렬을 상속하지 않습니다.

  • 뷰의 문자열 비교에서는 뷰의 기본 데이터 정렬을 사용합니다. 뷰의 기본 데이터 정렬을 변경하거나 재정의하려는 작업은 오류를 반환하며 실패합니다.

  • 다른 보기에서 보기를 만드는 경우 원본 보기의 데이터 정렬과 다른 데이터 정렬을 지정할 수 없습니다.

  • $lookup 또는 $graphLookup과 같이 여러 뷰를 포함하는 애그리게이션을 수행하는 경우 뷰의 데이터 정렬이 동일해야 합니다.

db.getCollectionInfos()db.getCollectionNames() 와 같이 collection을 나열하는 작업은 출력에 뷰를 포함합니다.

중요

뷰 정의는 공개입니다. 즉, 뷰에 대한 db.getCollectionInfos()explain 작업에는 뷰를 정의하는 파이프라인이 포함됩니다. 따라서 뷰 정의에 민감한 필드와 값을 직접 참조하지 않는 것이 좋습니다.

뷰를 제거하려면 뷰에서 db.collection.drop() 메서드를 사용합니다.

뷰를 삭제하고 다시 만들거나 collMod 명령을 사용하여 뷰를 수정할 수 있습니다.

다음 작업은 이 페이지에 언급된 제한 사항을 제외하고 뷰에 대한 지원을 제공합니다.

명령.
방법
create

다음 예시에서 사용할 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()를 사용하여 1학년 학생으로 제한되는 뷰를 만듭니다.

db.createView(
"firstYears",
"students",
[ { $match: { year: 1 } } ]
)

예를 들면 다음과 같습니다.

  • firstYears 새 뷰의 이름입니다.

  • students 뷰의 기반이 되는 컬렉션입니다.

  • $matchstudents 컬렉션의 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() 메서드를 사용하면 특정 옵션이 있는 컬렉션 또는 뷰를 만들 수 있습니다.

다음 예에서는 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에 대한 뷰를 만든 다음 해당 뷰에 대해 쿼리를 실행하는 것이 편리한 경우가 많습니다. 애플리케이션은 복잡한 파이프라인을 구성하거나 유지 관리할 필요 없이 뷰를 쿼리할 수 있습니다.

두 개의 샘플 컬렉션 inventoryorders를 만듭니다.

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 }
]
← 데이터베이스 및 컬렉션