$project (집계)
정의
호환성
다음 환경에서 호스팅되는 배포에 $project
사용할 수 있습니다.
MongoDB Atlas: 클라우드에서의 MongoDB 배포를 위한 완전 관리형 서비스
MongoDB Enterprise: MongoDB의 구독 기반 자체 관리 버전
MongoDB Community: MongoDB의 소스 사용 가능 무료 자체 관리 버전
구문
$project
단계의 프로토타입 형식은 다음과 같습니다.
{ $project: { <specification(s)> } }
$project
는 필드 포함, _id
필드 표시 안 함, 새 필드 추가, 기존 필드 값 재설정을 지정할 수 있는 문서를 사용합니다. 또는 필드 제외를 지정할 수 있습니다.
$project
사양의 형식은 다음과 같습니다.
형식 | 설명 |
---|---|
<field>: <1 or true> | 필드 포함 여부를 지정합니다. 0이 아닌 정수도 true 로 처리됩니다. |
_id: <0 or false> |
조건부로 필드를 제외하려면 |
<field>: <expression> | 새 필드를 추가하거나 기존 필드의 값을 재설정합니다. 표현식이 |
<field>: <0 or false> | 필드 제외 여부를 지정합니다. 조건부로 필드를 제외하려면
필드를 제외하려면 |
행동
필드 포함
_id
필드
_id
필드는 출력 문서에 포함되도록 기본 설정되어 있습니다. 출력 문서에서 _id
필드를 제외하려면 $project
에서 _id
필드를 사용하지 않음을 명시적으로 지정해야 합니다.
필드 제외하기
필드 제외를 지정하면 다른 모든 필드가 출력 문서에 반환됩니다.
{ $project: { "<field1>": 0, "<field2>": 0, ... } } // Return all but the specified fields
_id
이외의 필드를 제외하도록 지정하면 다른 $project
지정 양식을 사용할 수 없습니다. 즉, 필드를 제외하면 필드 포함을 지정하거나 기존 필드 값을 재설정하거나 새 필드를 추가할 수도 없습니다. 이 제한은 REMOVE
변수를 사용하여 필드를 조건부로 제외하는 경우에는 적용되지 않습니다.
필드를 제외하려면 $unset
단계도 참조하세요.
조건부로 필드 제외
집계 표현식에서 변수 REMOVE
(을)를 사용하여 조건부로 필드를 억제할 수 있습니다. 예시를 보려면 조건부로 필드 제외를 참조하세요.
새 필드 추가 또는 기존 필드 재설정
참고
MongoDB는 문서에 새 필드를 추가할 수 있는 $addFields
도 제공합니다.
새 필드를 추가하거나 기존 필드의 값을 재설정하려면 필드 이름을 지정하고 해당 값을 특정 표현식으로 설정합니다. 표현식에 대한 자세한 내용은 표현식 연산자를 참조하세요.
리터럴 값
필드를 리터럴로 리졸브되는 표현식으로 설정하는 대신 필드 값을 숫자 또는 부울 리터럴로 직접 설정하려면 $literal
연산자를 사용합니다. 그렇지 않으면 $project
가 숫자 또는 부울 리터럴을 필드를 포함하거나 제외할 때 플래그로 처리합니다.
필드 이름 바꾸기
새 필드를 지정하고 해당 값을 기존 필드의 필드 경로로 설정하면 필드 이름을 효과적으로 변경할 수 있습니다.
새 배열 필드
$project
단계는 대괄호 []
(을)를 사용해 새 배열 필드를 직접 만들 수 있도록 지원합니다. 문서에 존재하지 않는 배열 필드를 지정하는 경우, 연산은 해당 필드의 값으로 null
(을)를 대체합니다. 예시는 새 배열 필드 프로젝트를 참조하세요.
배열 인덱스는 $project
단계와 함께 사용할 수 없습니다. 자세한 내용은 배열 인덱스가 지원되지 않음을 참조하세요.
내장된 문서 필드
내장된 문서 내에서 필드를 프로젝션하거나 추가/재설정할 때 다음과 같이 점 표기법을 사용할 수 있습니다.
"contact.address.country": <1 or 0 or expression>
또는 필드를 중첩할 수도 있습니다:
contact: { address: { country: <1 or 0 or expression> } }
필드를 중첩할 때 내장된 문서 내에서 점 표기법을 사용하여 필드를 지정할 수 없습니다(예: contact: {
"address.country": <1 or 0 or expression> }
은(는) 유효하지 않습니다).
포함된 필드의 경로 충돌 오류
내장된 문서와 이 내장된 문서 내의 필드를 동일한 프로젝션에 모두 지정할 수는 없습니다.
다음 $project
단계는 내장된 contact
문서와 contact.address.country
필드를 모두 프로젝션하려고 시도하기 때문에 실패하며 Path collision
오류를 반환합니다.
{ $project: { contact: 1, "contact.address.country": 1 } }
이 오류는 상위 문서와 임베디드 필드가 지정된 순서와 관계없이 발생합니다. 다음 $project
도 동일한 오류로 인해 실패합니다.
{ $project: { "contact.address.country": 1, contact: 1 } }
$project
단계 배치
$project
단계를 사용하는 경우 이 단계는 일반적으로 파이프라인의 마지막 단계로, 클라이언트에 반환할 필드를 지정하는 데 사용됩니다.
파이프라인의 시작 또는 중간에 $project
단계를 사용하여 후속 파이프라인 단계로 전달되는 필드 수를 줄이면 데이터베이스에서 이 최적화를 자동으로 수행하므로 성능이 향상되지 않을 수 있습니다.
고려 사항
빈 사양
MongoDB는 $project
단계에 빈 문서가 전달되면 오류를 반환합니다.
예를 들어 다음 파이프라인을 실행하면 오류가 발생합니다.
db.myCollection.aggregate( [ { $project: { } } ] )
배열 인덱스
배열 인덱스는 $project
단계와 함께 사용할 수 없습니다. 자세한 내용은 배열 인덱스가 지원되지 않음을 참조하세요.
예시
출력 문서에 특정 필드 포함하기
다음 문서가 포함된 collection을 고려합니다:books
{ "_id" : 1, title: "abc123", isbn: "0001122223334", author: { last: "zzz", first: "aaa" }, copies: 5 }
다음 $project
단계는 출력 문서에 _id
, title
, author
필드만 포함합니다.
db.books.aggregate( [ { $project : { title : 1 , author : 1 } } ] )
이 연산을 수행하면 다음 문서가 생성됩니다.
{ "_id" : 1, "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }
출력 문서에서 _id
필드 표시 안 함
_id
필드는 기본적으로 항상 포함됩니다. $project
단계의 출력 문서에서 _id
필드를 제외하려면 프로젝션 문서에서 _id
필드를 0
으로 설정하여 제외를 지정합니다.
다음 문서가 포함된 collection을 고려합니다:books
{ "_id" : 1, title: "abc123", isbn: "0001122223334", author: { last: "zzz", first: "aaa" }, copies: 5 }
다음 $project
단계에서는 출력 문서에 _id
필드를 제외하지만 title
및 author
필드를 포함합니다.
db.books.aggregate( [ { $project : { _id: 0, title : 1 , author : 1 } } ] )
이 연산을 수행하면 다음 문서가 생성됩니다.
{ "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }
출력 문서에서 필드 제외
다음 문서가 포함된 collection을 고려합니다:books
{ "_id" : 1, title: "abc123", isbn: "0001122223334", author: { last: "zzz", first: "aaa" }, copies: 5, lastModified: "2016-07-28" }
다음 $project
단계에서는 출력에서 lastModified
필드를 제외합니다.
db.books.aggregate( [ { $project : { "lastModified": 0 } } ] )
필드를 제외하려면 $unset
단계도 참조하세요.
내장된 문서에서 필드 제외
다음 문서가 포함된 collection을 고려합니다:books
{ "_id" : 1, title: "abc123", isbn: "0001122223334", author: { last: "zzz", first: "aaa" }, copies: 5, lastModified: "2016-07-28" }
다음 $project
단계에서는 출력에서 author.first
및 lastModified
필드를 제외합니다.
db.books.aggregate( [ { $project : { "author.first" : 0, "lastModified" : 0 } } ] )
또는 문서에 제외 사양을 중첩할 수도 있습니다.
db.bookmarks.aggregate( [ { $project: { "author": { "first": 0}, "lastModified" : 0 } } ] )
두 사양 모두 동일한 출력이 생성됩니다.
{ "_id" : 1, "title" : "abc123", "isbn" : "0001122223334", "author" : { "last" : "zzz" }, "copies" : 5, }
필드를 제외하려면 $unset
단계도 참조하세요.
조건부 필드 제외
집계 표현식에서 변수 REMOVE
를 사용하여 조건부로 필드를 억제할 수 있습니다.
다음 문서가 포함된 collection을 고려합니다:books
{ "_id" : 1, title: "abc123", isbn: "0001122223334", author: { last: "zzz", first: "aaa" }, copies: 5, lastModified: "2016-07-28" } { "_id" : 2, title: "Baked Goods", isbn: "9999999999999", author: { last: "xyz", first: "abc", middle: "" }, copies: 2, lastModified: "2017-07-21" } { "_id" : 3, title: "Ice Cream Cakes", isbn: "8888888888888", author: { last: "xyz", first: "abc", middle: "mmm" }, copies: 5, lastModified: "2017-07-22" }
다음 $project
단계에서는 REMOVE
변수를 사용해 author.middle
필드가 ""
와 동일한 경우에만 제외합니다.
db.books.aggregate( [ { $project: { title: 1, "author.first": 1, "author.last" : 1, "author.middle": { $cond: { if: { $eq: [ "", "$author.middle" ] }, then: "$$REMOVE", else: "$author.middle" } } } } ] )
집계 연산을 수행하면 다음과 같은 결과가 출력됩니다.
{ "_id" : 1, "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } } { "_id" : 2, "title" : "Baked Goods", "author" : { "last" : "xyz", "first" : "abc" } } { "_id" : 3, "title" : "Ice Cream Cakes", "author" : { "last" : "xyz", "first" : "abc", "middle" : "mmm" } }
팁
$addFields와 비교
$addFields
또는 $project
단계를 사용하여 문서 필드를 제거할 수 있습니다. 파이프라인과 원본 문서를 얼마나 보존할 것인지에 따라 최적의 접근 방식이 달라질 수 있습니다.
$addFields
단계에서 $$REMOVE
사용하는 예시를 보려면 필드 제거를 참조하세요.
내장된 문서에서 특정 필드 포함하기
다음 문서가 포함된 bookmarks
collection을 생각해 보세요.
{ _id: 1, user: "1234", stop: { title: "book1", author: "xyz", page: 32 } } { _id: 2, user: "7890", stop: [ { title: "book2", author: "abc", page: 5 }, { title: "book3", author: "ijk", page: 100 } ] }
stop
필드의 내장된 문서에 title
필드만 포함하려면 점 표기법을 사용하면 됩니다.
db.bookmarks.aggregate( [ { $project: { "stop.title": 1 } } ] )
또는 문서에 포함 사양을 중첩할 수 있습니다.
db.bookmarks.aggregate( [ { $project: { stop: { title: 1 } } } ] )
두 사양 모두 다음과 같은 문서가 생성됩니다.
{ "_id" : 1, "stop" : { "title" : "book1" } } { "_id" : 2, "stop" : [ { "title" : "book2" }, { "title" : "book3" } ] }
계산된 필드 포함
다음 문서가 포함된 collection을 고려합니다:books
{ "_id" : 1, title: "abc123", isbn: "0001122223334", author: { last: "zzz", first: "aaa" }, copies: 5 }
다음 $project
단계에서는 새 필드 isbn
, lastName
및 copiesSold
를 추가합니다.
db.books.aggregate( [ { $project: { title: 1, isbn: { prefix: { $substr: [ "$isbn", 0, 3 ] }, group: { $substr: [ "$isbn", 3, 2 ] }, publisher: { $substr: [ "$isbn", 5, 4 ] }, title: { $substr: [ "$isbn", 9, 3 ] }, checkDigit: { $substr: [ "$isbn", 12, 1] } }, lastName: "$author.last", copiesSold: "$copies" } } ] )
이 연산을 수행하면 다음 문서가 생성됩니다.
{ "_id" : 1, "title" : "abc123", "isbn" : { "prefix" : "000", "group" : "11", "publisher" : "2222", "title" : "333", "checkDigit" : "4" }, "lastName" : "zzz", "copiesSold" : 5 }
새 배열 필드 프로젝트
예를 들어 컬렉션에 다음 문서가 포함되어 있다고 가정해 보겠습니다.
{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "x" : 1, "y" : 1 }
다음 작업은 x
및 y
필드를 새 필드 myArray
의 요소로 프로젝트합니다.
db.collection.aggregate( [ { $project: { myArray: [ "$x", "$y" ] } } ] )
연산은 다음 문서를 반환합니다.
{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "myArray" : [ 1, 1 ] }
배열 사양이 문서에 존재하지 않는 필드를 포함하는 경우 연산은 null
을 해당 필드의 값으로 대체합니다.
예를 들어 위와 동일한 문서가 주어졌을 때 다음 연산은 x
, y
필드와 존재하지 않는 필드 $someField
를 새 필드 myArray
의 요소로 투영합니다.
db.collection.aggregate( [ { $project: { myArray: [ "$x", "$y", "$someField" ] } } ] )
연산은 다음 문서를 반환합니다.
{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "myArray" : [ 1, 1, null ] }
배열 인덱스가 지원되지 않음
배열 인덱스는 $project
단계와 함께 사용할 수 없습니다. 이 섹션에서 예시를 함께 살펴봅시다.
다음 pizzas
컬렉션을 만듭니다:
db.pizzas.insert( [ { _id: 0, name: [ 'Pepperoni' ] }, ] )
다음 예시는 피자를 반환합니다.
db.pizzas.aggregate( [ { $project: { x: '$name', _id: 0 } }, ] )
예시 출력에서는 피자가 반환됩니다.
[ { x: [ 'Pepperoni' ] } ]
다음 예시는 배열 인덱스($name.0
)를 사용해 피자를 반환하려고 시도합니다.
db.pizzas.aggregate( [ { $project: { x: '$name.0', _id: 0 } }, ] )
예시 출력에서는 피자가 반환되지 않습니다:
[ { x: [] } ]