문서 메뉴
문서 홈
/
MongoDB 매뉴얼
/ / /

$replaceWith (aggregation)

이 페이지의 내용

  • 정의
  • 행동
  • 예제
$replaceWith

입력 문서를 지정된 문서로 바꿉니다. 이 작업은 _id 필드를 포함하여 입력 문서의 모든 기존 필드를 대체합니다. $replaceWith 를 사용하면 내장된 문서를 최상위 수준으로 승격할 수 있습니다. 새 문서를 대체 문서로 지정할 수도 있습니다.

$replaceWith 단계는 $replaceRoot 단계와 동일한 조치를 수행하지만 단계의 형태가 다릅니다.

$replaceWith 단계의 형식은 다음과 같습니다.

{ $replaceWith: <replacementDocument> }

대체 문서는 문서로 해석되는 모든 유효한 표현식일 수 있습니다. 표현식에 대한 자세한 내용은 표현식 연산자를 참조하세요.

<replacementDocument>가 문서가 아닌 경우 $replaceWith 오류가 발생하여 실패합니다.

<replacementDocument>가 누락된 문서(즉, 문서가 존재하지 않음)로 확인되면 $replaceWith 오류가 발생하고 실패합니다. 예를 들어, 다음 문서를 사용하여 컬렉션을 만듭니다.

db.collection.insertMany([
{ "_id": 1, "name" : { "first" : "John", "last" : "Backus" } },
{ "_id": 2, "name" : { "first" : "John", "last" : "McCarthy" } },
{ "_id": 3, "name": { "first" : "Grace", "last" : "Hopper" } },
{ "_id": 4, "firstname": "Ole-Johan", "lastname" : "Dahl" },
])

그러면 문서 중 하나에 name 필드가 없기 때문에 다음 $replaceWith 작업이 실패합니다.

db.collection.aggregate([
{ $replaceWith: "$name" }
])

오류를 방지하려면 $mergeObjects를 사용해 name 문서를 일부 기본 문서와 병합하면 됩니다. 그 예는 다음과 같습니다.

db.collection.aggregate([
{ $replaceWith: { $mergeObjects: [ { _id: "$_id", first: "", last: "" }, "$name" ] } }
])

또한, $match 단계를 포함해 $replaceWith 단계로 문서를 전달하기 전에 문서 필드의 존재 여부를 확인하여 name 필드가 누락된 문서를 건너뛸 수 있습니다.

db.collection.aggregate([
{ $match: { name : { $exists: true, $not: { $type: "array" }, $type: "object" } } },
{ $replaceWith: "$name" }
])

또는 $ifNull 표현식을 사용하여 다른 문서를 루트로 지정할 수 있습니다. 예:

db.collection.aggregate([
{ $replaceWith: { $ifNull: [ "$name", { _id: "$_id", missingName: true} ] } }
])

다음 문서를 사용하여 people 라는 이름의 샘플 collection을 생성합니다.

db.people.insertMany([
{ "_id" : 1, "name" : "Arlene", "age" : 34, "pets" : { "dogs" : 2, "cats" : 1 } },
{ "_id" : 2, "name" : "Sam", "age" : 41, "pets" : { "cats" : 1, "fish" : 3 } },
{ "_id" : 3, "name" : "Maria", "age" : 25 }
])

다음 작업은 $replaceWith 단계를 사용하여 각 입력 문서를 $mergeObjects 작업의 결과로 바꿉니다. $mergeObjects 표현식은 지정된 기본 문서를 pets 문서와 병합합니다.

db.people.aggregate( [
{ $replaceWith: { $mergeObjects: [ { dogs: 0, cats: 0, birds: 0, fish: 0 }, "$pets" ] } }
] )

이 연산은 다음과 같은 결과를 반환합니다.

{ "dogs" : 2, "cats" : 1, "birds" : 0, "fish" : 0 }
{ "dogs" : 0, "cats" : 1, "birds" : 0, "fish" : 3 }
{ "dogs" : 0, "cats" : 0, "birds" : 0, "fish" : 0 }

students라는 이름의 컬렉션에 다음 문서가 포함되어 있습니다.

db.students.insertMany([
{
"_id" : 1,
"grades" : [
{ "test": 1, "grade" : 80, "mean" : 75, "std" : 6 },
{ "test": 2, "grade" : 85, "mean" : 90, "std" : 4 },
{ "test": 3, "grade" : 95, "mean" : 85, "std" : 6 }
]
},
{
"_id" : 2,
"grades" : [
{ "test": 1, "grade" : 90, "mean" : 75, "std" : 6 },
{ "test": 2, "grade" : 87, "mean" : 90, "std" : 3 },
{ "test": 3, "grade" : 91, "mean" : 85, "std" : 4 }
]
}
])

다음 작업은 grade 필드가 90보다 크거나 같은 포함된 문서를 최상위 수준으로 승격합니다.

db.students.aggregate( [
{ $unwind: "$grades" },
{ $match: { "grades.grade" : { $gte: 90 } } },
{ $replaceWith: "$grades" }
] )

이 연산은 다음과 같은 결과를 반환합니다.

{ "test" : 3, "grade" : 95, "mean" : 85, "std" : 6 }
{ "test" : 1, "grade" : 90, "mean" : 75, "std" : 6 }
{ "test" : 3, "grade" : 91, "mean" : 85, "std" : 4 }

예제 collection sales은(는) 다음 문서로 채워집니다.

db.sales.insertMany([
{ "_id" : 1, "item" : "butter", "price" : 10, "quantity": 2, date: ISODate("2019-03-01T08:00:00Z"), status: "C" },
{ "_id" : 2, "item" : "cream", "price" : 20, "quantity": 1, date: ISODate("2019-03-01T09:00:00Z"), status: "A" },
{ "_id" : 3, "item" : "jam", "price" : 5, "quantity": 10, date: ISODate("2019-03-15T09:00:00Z"), status: "C" },
{ "_id" : 4, "item" : "muffins", "price" : 5, "quantity": 10, date: ISODate("2019-03-15T09:00:00Z"), status: "C" }
])

보고서를 만들기 위해 현재 보고서 실행 시간을 기준으로 완료된 각각의 판매에 대한 총액을 계산한다고 가정해 보겠습니다. 다음 연산은 $replaceWith 단계를 사용해 C 상태인 모든 판매를 찾아 새 문서를 생성합니다. $replaceWith는 총 금액을 계산하고 변수 NOW를 사용하여 현재 시간을 가져옵니다.

db.sales.aggregate([
{ $match: { status: "C" } },
{ $replaceWith: { _id: "$_id", item: "$item", amount: { $multiply: [ "$price", "$quantity"]}, status: "Complete", asofDate: "$$NOW" } }
])

이 작업은 다음 문서를 반환합니다.

{ "_id" : 1, "item" : "butter", "amount" : 20, "status" : "Complete", "asofDate" : ISODate("2019-06-03T22:47:54.812Z") }
{ "_id" : 3, "item" : "jam", "amount" : 50, "status" : "Complete", "asofDate" : ISODate("2019-06-03T22:47:54.812Z") }
{ "_id" : 4, "item" : "muffins", "amount" : 50, "status" : "Complete", "asofDate" : ISODate("2019-06-03T22:47:54.812Z") }

예시 collection reportedsales는 분기 및 지역별로 보고된 판매 정보로 채워집니다.

db.reportedsales.insertMany( [
{ _id: 1, quarter: "2019Q1", region: "A", qty: 400 },
{ _id: 2, quarter: "2019Q1", region: "B", qty: 550 },
{ _id: 3, quarter: "2019Q1", region: "C", qty: 1000 },
{ _id: 4, quarter: "2019Q2", region: "A", qty: 660 },
{ _id: 5, quarter: "2019Q2", region: "B", qty: 500 },
{ _id: 6, quarter: "2019Q2", region: "C", qty: 1200 }
] )

보고 목적으로 보고된 판매 데이터를 분기별로 조회려고 한다고 가정합니다. 예를 들어

{ "_id" : "2019Q1", "A" : 400, "B" : 550, "C" : 1000 }

분기별로 그룹화된 데이터를 보려면 다음 aggregation pipeline을 사용할 수 있습니다.

db.reportedsales.aggregate( [
{ $addFields: { obj: { k: "$region", v: "$qty" } } },
{ $group: { _id: "$quarter", items: { $push: "$obj" } } },
{ $project: { items2: { $concatArrays: [ [ { "k": "_id", "v": "$_id" } ], "$items" ] } } },
{ $replaceWith: { $arrayToObject: "$items2" } }
] )
첫 번째 단계:

$addFields 단계에서는 키 k 를 리전 값으로, 값 v를 해당 리전의 수량으로 정의하는 새 obj 문서 필드를 추가합니다. 예를 들면 다음과 같습니다.

{ "_id" : 1, "quarter" : "2019Q1", "region" : "A", "qty" : 400, "obj" : { "k" : "A", "v" : 400 } }
두 번째 단계:

$group 단계는 분기별로 그룹화하고 $push을(를) 사용하여 obj 필드를 새 items 배열 필드로 누적합니다. 예를 들면 다음과 같습니다.

{ "_id" : "2019Q1", "items" : [ { "k" : "A", "v" : 400 }, { "k" : "B", "v" : 550 }, { "k" : "C", "v" : 1000 } ] }
세 번째 단계:

$project 단계에서는 $concatArrays를 사용하여 _id 정보와 items 배열의 요소를 포함하는 새 배열 items2를 만듭니다.

{ "_id" : "2019Q1", "items2" : [ { "k" : "_id", "v" : "2019Q1" }, { "k" : "A", "v" : 400 }, { "k" : "B", "v" : 550 }, { "k" : "C", "v" : 1000 } ] }
네 번째 단계:

$replaceWith$arrayToObject를 사용하여 items2를 지정된 키 k와 값 v 쌍을 사용하며, 해당 문서를 다음 단계로 출력합니다. 예를 들면 다음과 같습니다.

{ "_id" : "2019Q1", "A" : 400, "B" : 550, "C" : 1000 }

애그리게이션은 다음 문서를 반환합니다.

{ "_id" : "2019Q1", "A" : 400, "B" : 550, "C" : 1000 }
{ "_id" : "2019Q2", "A" : 660, "B" : 500, "C" : 1200 }

다음 문서를 사용하여 contacts 라는 이름의 샘플 collection을 생성합니다.

db.contacts.insertMany( [
{ "_id" : 1, name: "Fred", email: "fred@example.net" },
{ "_id" : 2, name: "Frank N. Stine", cell: "012-345-9999" },
{ "_id" : 3, name: "Gren Dell", cell: "987-654-3210", email: "beo@example.net" }
] )

다음 연산은 $replaceWith$mergeObjects를 사용하여 누락된 필드에 대한 기본값이 있는 현재 문서를 출력합니다.

db.contacts.aggregate( [
{ $replaceWith:
{ $mergeObjects:
[
{ _id: "", name: "", email: "", cell: "", home: "" },
"$$ROOT"
]
}
}
] )

애그리게이션은 다음 문서를 반환합니다.

{
_id: 1,
name: 'Fred',
email: 'fred@example.net',
cell: '',
home: ''
},
{
_id: 2,
name: 'Frank N. Stine',
email: '',
cell: '012-345-9999',
home: ''
},
{
_id: 3,
name: 'Gren Dell',
email: 'beo@example.net',
cell: '',
home: '987-654-3210'
}
← $replaceRoot (aggregation)

이 페이지의 내용