정의
$replaceWithReplaces the input document with the specified document. The operation replaces all existing fields in the input document, including the
_idfield. With$replaceWith, you can promote an embedded document to the top-level. You can also specify a new document as the replacement.The
$replaceWithstage performs the same action as the$replaceRootstage, but the stages have different forms.The
$replaceWithstage has the following form:{ $replaceWith: <replacementDocument> } 대체 문서는 문서로 해석되는 모든 유효한 표현식 일 수 있습니다. 표현식에 대한 자세한 내용은 표현식을 참조하세요 .
행동
If the <replacementDocument> is not a document, $replaceWith errors and fails.
If the <replacementDocument> resolves to a missing document (i.e. the document does not exist), $replaceWith errors and fails. For example, create a collection with the following documents:
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" }, ])
Then the following $replaceWith operation fails because one of the document does not have the name field:
db.collection.aggregate([ { $replaceWith: "$name" } ])
오류를 방지하려면 $mergeObjects를 사용해 name 문서를 일부 기본 문서와 병합하면 됩니다. 그 예는 다음과 같습니다.
db.collection.aggregate([ { $replaceWith: { $mergeObjects: [ { _id: "$_id", first: "", last: "" }, "$name" ] } } ])
Alternatively, you can skip the documents that are missing the name field by including a $match stage to check for existence of the document field before passing documents to the $replaceWith stage:
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} ] } } ])
예시
$replaceWith 내장된 문서 필드
다음 문서를 사용하여 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 } ])
The following operation uses the $replaceWith stage to replace each input document with the result of a $mergeObjects operation. The $mergeObjects expression merges the specified default document with the pets document.
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 } ]
$replaceWith 배열에 중첩된 문서
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 } ]
$replaceWith 새로 생성된 문서
예시 1
예시 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" } ])
Assume that for reporting purposes, you want to calculate for each completed sale, the total amount as of the current report run time. The following operation finds all the sales with status C and creates new documents using the $replaceWith stage. The $replaceWith calculates the total amount as well as uses the variable NOW to get the current time.
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: '...' }, { _id: 3, item: 'jam', amount: 50, status: 'Complete', asofDate: '...' }, { _id: 4, item: 'muffins', amount: 50, status: 'Complete', asofDate: '...' } ]
예시 2
예시 컬렉션 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 }
분기별로 그룹화된 데이터를 보려면 다음 집계 파이프라인을 사용할 수 있습니다.
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 } ] } - 네 번째 단계:
The
$replaceWithuses the$arrayToObjectto convert theitems2into a document, using the specified keykand valuevpairs and outputs that document to the next stage. For example:{ "_id" : "2019Q1", "A" : 400, "B" : 550, "C" : 1000 }
집계는 다음 문서를 반환합니다.
[ { _id: '2019Q1', A: 400, B: 550, C: 1000 }, { _id: '2019Q2', A: 660, B: 500, C: 1200 } ]
$replaceWith $$ROOT 에서 생성된 새 문서와 기본 문서
다음 문서를 사용하여 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" } ] )
The following operation uses $replaceWith with $mergeObjects to output current documents with default values for missing fields:
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: '987-654-3210', home: '' } ]
이 페이지의 C# 예제에서는 Atlas 샘플 데이터 세트의 sample_mflix 데이터베이스 사용합니다. 무료 MongoDB Atlas cluster 생성하고 샘플 데이터 세트를 로드하는 방법을 학습하려면 MongoDB .NET/ C# 드라이버 문서에서 시작하기 를 참조하세요.
다음 Movie 클래스는 sample_mflix.movies 컬렉션의 문서를 모델링합니다.
[] public class Movie { [] public ObjectId Id { get; set; } [] public string Title { get; set; } = null!; [] public int? Year { get; set; } [] public int? Runtime { get; set; } [] public string? Rated { get; set; } [] public int Metacritic { get; set; } [] public string? Plot { get; set; } [] public string? Type { get; set; } [] public string[]? Cast { get; set; } [] public string[]? Directors { get; set; } [] public string[]? Writers { get; set; } [] public ImdbData? Imdb { get; set; } }
다음 ImdbData 클래스는 각 Movie의 imdb 필드에 있는 내장된 문서를 모델링합니다.
[] public class ImdbData { [] public int? ImdbId { get; set; } [] public double? Rating { get; set; } [] public int? Votes { get; set; } }
To use the MongoDB .NET/C# driver to add a $replaceWith stage to an aggregation pipeline, call the UnionWith() method on a PipelineDefinition object.
다음 예시는 제목을 기준으로 Movie 문서를 알파베슷 순으로 정렬하고, 결과를 5개 문서로 제한하고, 각 Movie 문서를 Imdb 속성에 저장된 ImdbData 문서로 대체하는 파이프라인 단계를 만듭니다.
var pipeline = new EmptyPipelineDefinition<Movie>() .Sort(Builders<Movie>.Sort.Ascending(m => m.Title)) .Limit(5) .ReplaceWith(m => m.Imdb);
이 페이지의 Node.js 예제에서는 Atlas 샘플 데이터 세트의 sample_mflix 데이터베이스 사용합니다. 무료 MongoDB Atlas cluster 생성하고 샘플 데이터 세트를 로드하는 방법을 학습하려면 MongoDB Node.js 운전자 설명서에서 시작하기 를 참조하세요.
MongoDB Node.js 운전자 사용하여 집계 파이프라인 에 $replaceWith 단계를 추가하려면 파이프라인 객체 에서 $replaceWith 연산자 사용합니다.
다음 예시 각 입력 movie 문서 imdb 필드 에 저장된 문서 로 대체하는 파이프라인 단계를 만듭니다. 그런 다음 이 예시 에서는 집계 파이프라인 실행합니다.
const pipeline = [{ $replaceWith: '$imdb' }]; const cursor = collection.aggregate(pipeline); return cursor;
자세히 알아보기
관련 파이프라인 단계에 대해 자세히 학습 $replaceRoot 가이드 참조하세요.