문서 메뉴

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

뷰 만들기 및 쿼리

이 페이지의 내용

  • db.createCollection() 구문
  • db.createView() 구문
  • 제한 사항
  • 지원되지 않는 작업
  • 예제
  • 컬렉션 채우기
  • db.createView()를 사용하여 뷰 만들기
  • db.createCollection()을 사용하여 뷰 만들기
  • 현재 사용자에게 부여된 역할에 대한 의료 정보 조회
  • 현재 사용자에게 부여된 역할에 대한 예산 문서 조회
  • 여러 데이터베이스에서 동일한 이름을 가진 역할
  • 행동
  • 애그리게이션 최적화
  • 리소스 잠금

뷰를 만들려면 다음 방법 중 하나를 사용합니다.

MongoDB Atlas UI에서 뷰를 만들려면 구체화된 뷰를 사용해야 합니다. 자세히 알아보려면 MongoDB Atlas UI에서 구체화된 뷰 만들기를 참조하세요.

중요

컬렉션 목록 출력에 뷰 이름이 포함됨

db.getCollectionInfos()db.getCollectionNames() 같이 컬렉션을 나열하는 연산은 출력에 뷰를 포함합니다.

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

db.createCollection(
"<viewName>",
{
"viewOn" : "<source>",
"pipeline" : [<pipeline>],
"collation" : { <collation> }
}
)
db.createView(
"<viewName>",
"<source>",
[<pipeline>],
{
"collation" : { <collation> }
}
)
  • 원본 컬렉션과 동일한 데이터베이스에 뷰를 만들어야 합니다.

  • 보기 정의 pipeline에는 $out 또는 $merge 단계를 포함할 수 없습니다. 이 제한은 $lookup 단계 또는 $facet 단계에서 사용되는 파이프라인과 같은 임베디드 파이프라인에도 적용됩니다.

  • 뷰를 만든 후에는 이름을 변경할 수 없습니다.

일부 작업은 뷰에서 사용할 수 없습니다.

  • db.collection.mapReduce().

  • 집계에서 $text 연산은 첫 번째 단계에만 유효하므로 $text 연산자를 사용할 수 없습니다.

  • 뷰 이름 변경.

자세한 내용은 뷰에 대해 지원되는 작업을 참조하세요.

첫 번째 예에서는 학생 데이터로 컬렉션을 채우고 데이터를 쿼리하는 뷰를 만듭니다.

이 예제에 사용할 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 }
]

참고

프로젝션 제한 사항

뷰에 대한 find() 작업은 다음 쿼리 및 투영 연산자 연산자를 지원하지 않습니다.

db.createCollection() 메서드를 사용하면 특정 옵션이 있는 컬렉션 또는 뷰를 만들 수 있습니다.

다음 예에서는 graduateStudents 뷰를 만듭니다. 뷰에는 $match 단계에서 선택한 문서만 포함되어 있습니다. 선택적 데이터 정렬 설정에 따라 정렬 순서가 결정됩니다.

db.createCollection(
"graduateStudents",
{
viewOn: "students",
pipeline: [ { $match: { $expr: { $gt: [ "$year", 4 ] } } } ],
collation: { locale: "en", caseFirst: "upper" }
}
)

참고

데이터 정렬 동작

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

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

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

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

다음 예제에서는 보기를 쿼리합니다. $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 }
]

MongoDB 7.0부터는 새로운 USER_ROLES 시스템 변수를 사용하여 사용자 역할을 반환할 수 있습니다.

이 섹션의 예에서는 의료 정보가 포함된 컬렉션의 필드에 대한 접근 권한이 제한된 사용자를 보여줍니다. 이 예제에서는 USER_ROLES 시스템 변수에서 현재 사용자 역할을 읽고 역할에 따라 필드를 숨기는 뷰를 사용합니다.

이 예제에서는 다음과 같은 사용자를 생성합니다.

  • James creditCard 필드에 액세스할 수 있는 Billing 역할로 바꿉니다.

  • Michelle diagnosisCode 필드에 액세스할 수 있는 Provider 역할로 바꿉니다.

다음 단계를 수행하여 역할, 사용자, 컬렉션 및 뷰를 만듭니다.

1

실행:

db.createRole( { role: "Billing", privileges: [ { resource: { db: "test",
collection: "medicalView" }, actions: [ "find" ] } ], roles: [ ] } )
db.createRole( { role: "Provider", privileges: [ { resource: { db: "test",
collection: "medicalView" }, actions: [ "find" ] } ], roles: [ ] } )
2

필수 역할로 JamesMichelle이라는 이름의 사용자를 만듭니다. test 데이터베이스를 데이터베이스 이름으로 바꿉니다.

db.createUser( {
user: "James",
pwd: "js008",
roles: [
{ role: "Billing", db: "test" }
]
} )
db.createUser( {
user: "Michelle",
pwd: "me009",
roles: [
{ role: "Provider", db: "test" }
]
} )
3

실행:

db.medical.insertMany( [
{
_id: 0,
patientName: "Jack Jones",
diagnosisCode: "CAS 17",
creditCard: "1234-5678-9012-3456"
},
{
_id: 1,
patientName: "Mary Smith",
diagnosisCode: "ACH 01",
creditCard: "6541-7534-9637-3456"
}
] )
4

시스템 변수를 사용하려면 변수 이름 시작 부분에 $$를 추가합니다. USER_ROLES 시스템 변수를 $$USER_ROLES로 지정합니다.

보기는 USER_ROLES 시스템 변수에서 현재 사용자 역할을 읽고 역할에 따라 필드를 숨깁니다.

실행:

db.createView(
"medicalView", "medical",
[ {
$set: {
"diagnosisCode": {
$cond: {
if: { $in: [
"Provider", "$$USER_ROLES.role"
] },
then: "$diagnosisCode",
else: "$$REMOVE"
}
}
},
}, {
$set: {
"creditCard": {
$cond: {
if: { $in: [
"Billing", "$$USER_ROLES.role"
] },
then: "$creditCard",
else: "$$REMOVE"
}
}
}
} ]
)

뷰 예시

  • Provider 역할을 가진 사용자에 대한 diagnosisCode 필드를 포함합니다.

  • Billing 역할을 가진 사용자에 대한 creditCard 필드를 포함합니다.

  • $set 파이프라인 단계와 $$REMOVE 사용하여 뷰를 쿼리하는 사용자에게 $$USER_ROLES.role에 반환된 일치하는 역할이 있는지 여부에 따라 필드를 숨깁니다.

James 에 액세스할 수 있는 정보를 검색하려면 다음 단계를 수행하십시오.

1

실행:

db.auth( "James", "js008" )
2

실행:

db.medicalView.find()
3

James Billing 역할을 갖고 있으며 creditCard 필드를 포함하지만, diagnosisCode 필드는 포함하지 않는 다음과 같은 문서를 볼 수 있습니다.

[
{
_id: 0, patientName: 'Jack Jones',
creditCard: '1234-5678-9012-3456'
},
{
_id: 1, patientName: 'Mary Smith',
creditCard: '6541-7534-9637-3456'
}
]

Michelle 에 액세스할 수 있는 정보를 검색하려면 다음 단계를 수행하십시오.

1

실행:

db.auth( "Michelle", "me009" )
2

실행:

db.medicalView.find()
3

Michelle Provider 역할을 갖고 있으며 diagnosisCode 필드를 포함하지만, creditCard 필드는 포함하지 않는 다음과 같은 문서를 볼 수 있습니다.

[
{ _id: 0, patientName: 'Jack Jones',
diagnosisCode: 'CAS 17' },
{ _id: 1, patientName: 'Mary Smith',
diagnosisCode: 'ACH 01' }
]

MongoDB 7.0부터는 새로운 USER_ROLES 시스템 변수를 사용하여 사용자 역할을 반환할 수 있습니다.

이 섹션의 시나리오에서는 예산 정보가 포함된 컬렉션의 문서에 대한 액세스 권한이 제한된 다양한 역할의 사용자를 보여줍니다.

이 시나리오는 USER_ROLES의 한 가지 가능한 용도를 보여 줍니다. budget collection에는 allowedRoles(이)라는 필드가 있는 문서가 포함되어 있습니다. 다음 시나리오에서 볼 수 있듯이 allowedRoles 필드에 있는 사용자 역할을 USER_ROLES 시스템 변수에서 반환한 역할과 비교하는 쿼리를 쓸 수 있습니다.

참고

다른 USER_ROLES 예시 시나리오는 현재 사용자에게 부여된 역할에 대한 의료 정보 조회를 참조하세요. 이 예제에서는 다음 예제에서처럼 문서 필드에 사용자 역할을 저장하지 않습니다.

이 섹션의 예산 시나리오의 경우 다음 단계를 수행하여 역할, 사용자 및 budget 컬렉션을 만들 수 있습니다.

1

실행:

db.createRole( { role: "Marketing", roles: [], privileges: [] } )
db.createRole( { role: "Sales", roles: [], privileges: [] } )
db.createRole( { role: "Development", roles: [], privileges: [] } )
db.createRole( { role: "Operations", roles: [], privileges: [] } )
2

필수 역할로 JohnJane이라는 이름의 사용자를 만듭니다. test 데이터베이스를 데이터베이스 이름으로 바꿉니다.

db.createUser( {
user: "John",
pwd: "jn008",
roles: [
{ role: "Marketing", db: "test" },
{ role: "Development", db: "test" },
{ role: "Operations", db: "test" },
{ role: "read", db: "test" }
]
} )
db.createUser( {
user: "Jane",
pwd: "je009",
roles: [
{ role: "Sales", db: "test" },
{ role: "Operations", db: "test" },
{ role: "read", db: "test" }
]
} )
3

실행:

db.budget.insertMany( [
{
_id: 0,
allowedRoles: [ "Marketing" ],
comment: "For marketing team",
yearlyBudget: 15000
},
{
_id: 1,
allowedRoles: [ "Sales" ],
comment: "For sales team",
yearlyBudget: 17000,
salesEventsBudget: 1000
},
{
_id: 2,
allowedRoles: [ "Operations" ],
comment: "For operations team",
yearlyBudget: 19000,
cloudBudget: 12000
},
{
_id: 3,
allowedRoles: [ "Development" ],
comment: "For development team",
yearlyBudget: 27000
}
] )

뷰를 생성하고 John 에 액세스할 수 있는 문서를 검색하려면 다음 단계를 수행하세요.

1

시스템 변수를 사용하려면 변수 이름 시작 부분에 $$를 추가합니다. USER_ROLES 시스템 변수를 $$USER_ROLES로 지정합니다.

실행:

db.createView(
"budgetView", "budget",
[ {
$match: {
$expr: {
$not: {
$eq: [ { $setIntersection: [ "$allowedRoles", "$$USER_ROLES.role" ] }, [] ]
}
}
}
} ]
)

뷰를 생성할 수 없는 경우 뷰를 생성할 수 있는 권한이 있는 사용자로 로그인했는지 확인합니다.

이전 예제에서는 예제를 실행하는 사용자가 가진 역할 중 하나 이상과 일치하는 budget 컬렉션의 문서를 반환합니다. 이를 위해 이 예제에서는 $setIntersection을 사용하여 budget 문서 allowedRoles 필드와 $$USER_ROLES의 사용자 역할 세트 사이의 교집합이 비어 있지 않은 문서를 반환합니다.

2

실행:

db.auth( "John", "jn008" )
3

실행:

db.budgetView.find()
4

John Marketing, OperationsDevelopment역할이 있으며 다음과 같은 문서를 볼 수 있습니다.

[
{
_id: 0,
allowedRoles: [ 'Marketing' ],
comment: 'For marketing team',
yearlyBudget: 15000
},
{
_id: 2,
allowedRoles: [ 'Operations' ],
comment: 'For operations team',
yearlyBudget: 19000,
cloudBudget: 12000
},
{
_id: 3,
allowedRoles: [ 'Development' ],
comment: 'For development team',
yearlyBudget: 27000
}
]

Jane이 액세스할 수 있는 문서를 검색하려면 다음 단계를 수행하세요.

1

실행:

db.auth( "Jane", "je009" )
2

실행:

db.budgetView.find()
3

Jane 은(는) SalesOperations 역할을 가지며 다음과 같은 문서를 볼 수 있습니다.

[
{
_id: 1,
allowedRoles: [ 'Sales' ],
comment: 'For sales team',
yearlyBudget: 17000,
salesEventsBudget: 1000
},
{
_id: 2,
allowedRoles: [ 'Operations' ],
comment: 'For operations team',
yearlyBudget: 19000,
cloudBudget: 12000
}
]

참고

샤드 클러스터에서는 사용자를 대신하여 다른 서버 노드가 샤드에서 쿼리를 실행할 수 있습니다. 이러한 쿼리에서 USER_ROLES는 여전히 사용자에 대한 역할로 채워져 있습니다.

동일한 이름의 역할이 여러 데이터베이스에 있을 수 있습니다. 뷰를 만들고 뷰에서 특정 역할을 참고하는 경우 db 데이터베이스 이름 필드와 role 필드를 모두 지정하거나 데이터베이스 이름과 역할이 포함된 _id 필드를 지정해야 합니다.

다음 예에서는 다른 이름의 역할이 있는 Jane 에 할당된 역할을 반환합니다. 이 예에서는 _id, roledb 데이터베이스 이름을 반환합니다:

1

실행:

db.auth( "Jane", "je009" )
2

실행:

db.budget.findOne( {}, { myRoles: "$$USER_ROLES" } )
3

myRoles 배열의 _id, roledb 데이터베이스 이름을 보여주는 예제 출력:

{
_id: 0,
myRoles: [
{ _id: 'test.Operations', role: 'Operations', db: 'test' },
{ _id: 'test.Sales', role: 'Sales', db: 'test' },
{ _id: 'test.read', role: 'read', db: 'test' }
]
}

다음 섹션에서는 뷰 만들기 및 쿼리의 동작에 대해 설명합니다.

뷰를 쿼리하는 경우:

  • db.collection.find() 에 대한 쿼리 filter, projection, sort, skip, limit 및 기타 작업은 해당 aggregation pipeline 단계로변환됩니다.

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

  • aggregation pipeline 옵티마이저는 성능을 향상시키기 위해 뷰 aggregation pipeline 스테이지를 재구성합니다. 최적화로 인해 쿼리 결과가 변경되지는 않습니다.

db.createView() 은(는) 작업 기간 동안 지정된 컬렉션 또는 뷰에 대한 배타적 잠금을 얻습니다. 컬렉션에 대한 모든 후속 작업은 db.createView()이(가) 잠금을 해제할 때까지 기다려야 합니다. db.createView() 은(는) 일반적으로 짧은 시간 동안 이 잠금을 유지합니다.

뷰를 만들려면 데이터베이스의 system.views 컬렉션에 대한 추가 독점 잠금을 얻어야 합니다. 이 잠금은 명령이 완료될 때까지 데이터베이스의 뷰 생성 또는 수정을 차단합니다.

← 조회수