Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs Menu
Docs Home
/ /

$merge (집계 단계)

참고

이 페이지에서는 집계 파이프라인 결과를 컬렉션으로 출력하는 $merge 단계를 설명합니다. $mergeObjects 연산자는 문서를 단일 문서로 병합합니다. $mergeObjects를 참조하세요.

$merge

집계 파이프라인의 결과를 지정된 컬렉션에 씁니다. $merge 연산자는 파이프라인의 마지막 단계여야 합니다.

$merge 단계:

  • 동일하거나 다른 데이터베이스의 컬렉션으로 출력할 수 있습니다.

  • 집계 중인 동일한 컬렉션으로 출력할 수 있습니다. 자세한 내용은 집계 중인 동일한 컬렉션에 출력하기를 참조하세요.

  • 집계 파이프라인에서 $merge 또는 $out 단계를 사용할 때 다음 사항을 고려하세요.

    • MongoDB 5.0부터 $merge 단계가 있는 파이프라인은 클러스터의 모든 노드에서 featureCompatibilityVersion5.0 이상으로 설정되어 있고 읽기 설정이 세컨더리 읽기를 허용하는 경우 복제본 세트 세컨더리 노드에서 실행될 수 있습니다.

      • $merge $out 단계는 세컨더리 노드에서 실행되지만 쓰기 작업은 프라이머리 노드로 전송됩니다.

      • 모든 드라이버 버전이 보조 노드로 전송되는 $merge 연산을 지원하는 것은 아닙니다. 자세한 내용은 드라이버 설명서를 참조하세요.

    • 이전 MongoDB 버전에서는 $out 또는 $merge 단계가 있는 파이프라인은 항상 기본 노드에서 실행되며 읽기 기본 설정은 고려되지 않았습니다.

  • 출력 컬렉션이 아직 존재하지 않는 경우 새 컬렉션을 생성합니다.

  • 결과(새 문서 삽입, 문서 병합, 문서 교체, 기존 문서 유지, 작업 실패, 사용자 지정 업데이트 파이프라인으로 문서 처리)를 기존 컬렉션에 통합할 수 있습니다.

  • 샤드된 컬렉션으로 출력할 수 있습니다. 입력 컬렉션도 샤딩할 수 있습니다.

집계 결과를 컬렉션으로 출력하는 $out 단계와 비교하려면 $merge$out 비교를 참조하세요.

참고

온디맨드 구체화된 보기

$merge 컬렉션을 완전히 교체하는 대신 파이프라인 결과를 기존 출력 컬렉션에 통합할 수 있습니다. 이 기능을 사용하면 파이프라인이 실행될 때 출력 컬렉션의 콘텐츠가 점진적으로 업데이트되는 온디맨드 구체화된 보기를 만들 수 있습니다.

이 사용 사례에 대한 자세한 내용은 이 페이지의 예시 및 온디맨드 구체화된 뷰를 참조하세요.

구체화된 보기는 읽기 전용 보기와 별개입니다. 읽기 전용 보기를 만드는 방법에 대한 자세한 내용은 읽기 전용 보기를 참조하십시오.

다음 환경에서 호스팅되는 배포에 $merge 사용할 수 있습니다.

  • MongoDB Atlas: 클라우드에서의 MongoDB 배포를 위한 완전 관리형 서비스

$merge 의 구문은 다음과 같습니다:

{ $merge: {
into: <collection> -or- { db: <db>, coll: <collection> },
on: <identifier field> -or- [ <identifier field1>, ...], // Optional
let: <variables>, // Optional
whenMatched: <replace|keepExisting|merge|fail|pipeline>, // Optional
whenNotMatched: <insert|discard|fail> // Optional
} }

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

{ $merge: { into: "myOutput", on: "_id", whenMatched: "replace", whenNotMatched: "insert" } }

동일한 데이터베이스의 컬렉션에 쓰는 것을 포함하여 $merge에 대한 모든 기본 옵션을 사용하는 경우 간소화된 양식을 사용할 수 있습니다.

{ $merge: <collection> } // Output collection is in the same database

$merge 단계에서는 다음 필드가 있는 문서를 사용합니다.

필드
설명

출력 컬렉션입니다. 다음 중 하나를 지정합니다.

  • 집계가 실행되는 동일한 데이터베이스의 컬렉션에 출력할 문자열인 컬렉션 이름입니다. 예시:

    into: "myOutput"

  • 지정된 데이터베이스의 컬렉션으로 출력할 문서의 데이터베이스 및 컬렉션 이름입니다. 예시:

    into: { db:"myDB", coll:"myOutput" }

출력 컬렉션이 존재하지 않으면 $merge가 컬렉션을 생성합니다.

  • 복제본 세트 또는 독립형의 경우 출력 데이터베이스가 존재하지 않으면 $merge도 데이터베이스를 생성합니다.

  • 샤딩된 클러스터의 경우 지정된 출력 데이터베이스가 이미 존재해야 합니다.

출력 컬렉션은 샤드된 컬렉션일 수 있습니다.

선택 사항. 문서 의 고유 식별자 역할을 하는 필드입니다. 식별자는 결과 문서 출력 컬렉션 의 기존 문서 와 일치하는지 여부를 결정합니다. 다음 중 하나를 지정합니다.

  • 단일 필드 이름을 문자열로 입력합니다. 예시:

    on: "_id"

  • 배열의 필드 조합입니다. 예시:

    on: [ "date", "customerId" ]
    The order of the fields in the array does not matter, and you cannot specify the same field multiple times.

지정된 필드에 대해

  • 집계 결과 문서에는 on 필드가 _id 필드가 아닌 한 on에 지정된 필드가 포함되어야 합니다. 결과 문서에서 _id 필드가 누락된 경우, MongoDB가 자동으로 추가합니다.

  • 지정한 필드에 하나 이상의 필드에 널 또는 배열 값을 포함할 수 없습니다.

$merge 고유 인덱스에는 키가 on 식별자 필드에 해당해야 합니다. 인덱스 키 지정 순서는 중요하지 않지만 고유 인덱스는 반드시 on 필드만 키로 포함해야 합니다.

  • 또한 인덱스는 집계의 데이터 정렬과 동일한 데이터 정렬을 가져야 합니다.

  • 고유 인덱스는 희소 인덱스일 수 있습니다.

  • 고유 인덱스는 부분 인덱스일 수 없습니다.

  • 이미 존재하는 출력 컬렉션의 경우 해당 인덱스가 이미 존재해야 합니다.

on의 기본값 은 출력 컬렉션 에 따라 다릅니다.

선택 사항입니다. 결과 문서와 컬렉션의 기존 문서가 지정된 on 필드에 대해 동일한 값을 갖는 경우의 $merge 동작입니다.

다음 두 가지 중 하나를 지정할 수 있습니다.

  • 미리 정의된 동작 문자열 중 하나입니다.

    작업
    설명

    출력 컬렉션 의 기존 문서 일치하는 결과 문서 로 바꿉니다.

    바꾸기를 수행할 때 대체 문서로 인해 _id 값이 수정될 수 없으며 출력 컬렉션이 샤딩된 경우 샤드 키 값도 수정할 수 없습니다. 그렇지 않으면 작업이 오류를 생성합니다.

    이 오류를 방지하려면 on 필드 필드 포함되지 _id 않은 _id 경우 $unset 집계 결과에서 필드 제거 이전 단계 등에서 오류를 방지합니다.

    일치하는 문서를 병합합니다($mergeObjects 연산자와 유사).

    • 결과 문서에 기존 문서에 없는 필드가 포함된 경우 이러한 새 필드를 기존 문서에 추가합니다.

    • 결과 문서에 기존 문서의 필드가 포함된 경우 기존 필드 값을 결과 문서의 값으로 바꿉니다.

    예를 들어 출력 컬렉션에 문서가 있는 경우입니다.

    { _id: 1, a: 1, b: 1 }

    그리고 집계 결과에는 문서가 있습니다.

    { _id: 1, b: 5, z: 1 }

    그러면 병합된 문서가 됩니다.

    { _id: 1, a: 1, b: 5, z: 1 }

    병합을 수행할 때 병합된 문서로 인해 _id 값이 수정될 수 없으며 출력 컬렉션이 샤딩된 경우 샤드 키 값도 수정할 수 없습니다. 그렇지 않으면 작업이 오류를 생성합니다.

    이 오류를 방지하려면 on 필드 필드 포함되지 _id 않은 _id 경우 $unset 집계 결과에서 필드 제거 이전 단계 등에서 오류를 방지합니다.

    집계 작업을 중지하고 실패합니다. 이전 문서의 출력 컬렉션에 대한 변경 사항은 반환되지 않습니다.

  • 컬렉션의 문서를 업데이트하기 위한 집계 파이프라인입니다.

    [ <stage1>, <stage2> ... ]

    파이프라인은 다음 단계로만 구성될 수 있습니다.

    파이프라인 on 필드의 값을 수정할 수 없습니다. 예시 들어 month 필드 에서 일치하는 경우 파이프라인 month 필드 수정할 수 없습니다.

    whenMatched pipeline$<field>를 사용해 출력 컬렉션에 있는 기존 문서의 필드에 직접 액세스할 수 있습니다.

    집계 결과 문서의 필드에 액세스하려면 다음 중 하나를 사용합니다.

    • 필드 액세스 위한 내장 $$new 변수입니다. 구체적으로는 $$new.<field>입니다. 변수는 let $$new 지정이 생략된 경우에만 사용할 수 있습니다.

    • let 필드 의 사용자 정의 변수입니다.

      변수 이름과 함께 이중 달러 기호 ($$) 접두사를 $$<variable_name> 형식으로 지정합니다. 예시: $$year. 변수가 문서로 설정된 경우 $$<variable_name>.<field> 형식으로 문서 필드를 포함할 수도 있습니다. 예시: $$year.month.

      더 많은 예제는 변수를 사용하여 병합을 사용자 지정하기를 참조하세요.

선택 사항. whenMatched 파이프라인 에서사용할 변수를 지정합니다.

변수 이름과 값 표현식이 있는 문서를 지정합니다.

{ <variable_name_1>: <expression_1>,
...,
<variable_name_n>: <expression_n> }

지정하지 않으면 기본값은 { new: "$$ROOT" } 입니다(ROOT 참조). whenMatched 파이프라인 변수 액세스 할 수 $$new 있습니다.

whenMatched 파이프라인의 변수 액세스 하려면 다음을 수행합니다.

변수 이름과 함께 이중 달러 기호 ($$) 접두사를 $$<variable_name> 형식으로 지정합니다. 예시: $$year. 변수가 문서로 설정된 경우 $$<variable_name>.<field> 형식으로 문서 필드를 포함할 수도 있습니다. 예시: $$year.month.

예제는 변수를 사용하여 병합을 사용자 지정하기를 참조하세요.

선택 사항입니다. 결과 문서가 아웃 컬렉션의 기존 문서와 일치하지 않는 경우 $merge의 동작입니다.

미리 정의된 동작 문자열 중 하나를 지정할 수 있습니다:

작업
설명

"insert" (Default)

문서를 출력 컬렉션에 삽입합니다.

문서를 삭제합니다. 특히 $merge는 문서를 출력 컬렉션에 삽입하지 않습니다.

집계 작업을 중지하고 실패합니다. 출력 컬렉션에 이미 기록된 변경 사항은 반환되지 않습니다.

집계 파이프라인 결과에서 _id 필드가 문서에 없는 경우 $merge 단계에서 자동으로 생성합니다.

예를 들어, 다음 집계 파이프라인에서 $project$merge에 전달된 문서에서 _id 필드를 제외합니다. $merge가 문서를 "newCollection"에 쓸 때, $merge는 새 _id 필드와 값을 생성합니다.

db.movies.aggregate( [
{ $project: { _id: 0 } },
{ $merge : { into : "newCollection" } }
] )

지정한 출력 컬렉션이 없는 경우 $merge 작업은 새 컬렉션을 생성합니다.

  • 출력 컬렉션은 $merge 가 컬렉션에 첫 번째 문서를 쓸 때 생성되며 즉시 표시됩니다.

  • 집계에 실패하면 오류가 발생하기 전에 $merge가 완료한 모든 쓰기는 롤백되지 않습니다.

참고

복제본 세트 또는 독립형의 경우 출력 데이터베이스가 존재하지 않으면 $merge도 데이터베이스를 생성합니다.

샤딩된 클러스터의 경우 지정된 출력 데이터베이스가 이미 존재해야 합니다.

출력 컬렉션이 존재하지 않는 경우, $mergeon 식별자가 _id 필드여야 합니다. 존재하지 않는 컬렉션에 다른 on 필드 값을 사용하려면 먼저 원하는 필드에 고유 인덱스를 생성하여 컬렉션을 만들 수 있습니다. 예를 들어 출력 컬렉션 newDailyCommentCount가 존재하지 않고 commentDate 필드를 on 식별자로 지정하려는 경우입니다.

db.newDailyCommentCount.createIndex(
{ commentDate: 1 }, { unique: true } )
db.comments.aggregate( [
{ $match: { date: { $gte: new Date("2002-01-01"),
$lt: new Date("2002-02-01") } } },
{ $group: { _id: { $dateToString: { format: "%Y-%m-%d",
date: "$date" } }, count: { $sum: 1 } } },
{ $project: { _id: 0, commentDate: { $toDate: "$_id" },
count: 1 } },
{ $merge : { into : "newDailyCommentCount",
on: "commentDate" } }
] )

$merge 단계는 샤딩된 컬렉션으로 출력할 수 있습니다. 출력 컬렉션이 샤딩되면 $merge_id 필드와 모든 샤드 키 필드를 기본값 on 식별자로 사용합니다. 기본값을 재정의하는 경우, on 식별자에는 모든 샤드 키 필드가 포함되어야 합니다.

{ $merge: {
into: "<shardedColl>" or { db:"<sharding enabled db>", coll: "<shardedColl>" },
on: [ "<shardkeyfield1>", "<shardkeyfield2>",... ], // Shard key fields and any additional fields
let: <variables>, // Optional
whenMatched: <replace|keepExisting|merge|fail|pipeline>, // Optional
whenNotMatched: <insert|discard|fail> // Optional
} }

예를 들어 sh.shardCollection() 메서드를 사용하여 rated 필드를 샤드 키로 사용하여 새 샤드된 컬렉션 moviesByYearAndRating를 만듭니다.

sh.shardCollection(
"sample_mflix.moviesByYearAndRating", // Namespace of the collection to shard
{ rated: 1 }, // Shard key
);

moviesByYearAndRating 컬렉션에는 연도별(year 필드)과 콘텐츠 등급(샤드 키)별 영화 통계가 포함된 문서가 포함됩니다. 즉, on 식별자는 ["year", "rated"] 입니다(필드 순서는 중요하지 않음). $merge에는 on 식별자 필드에 해당하는 키가 있는 고유 인덱스가 필요하므로 고유 인덱스를 생성합니다(필드 순서는 중요하지 않음).[1]

db.moviesByYearAndRating.createIndex(
{ rated: 1, year: 1 }, { unique: true } )

샤딩된 컬렉션 moviesByYearAndRating과 생성된 고유 인덱스를 사용하면 $merge를 사용하여 이 컬렉션에 집계 결과를 출력하고, 이 예시에서처럼 [ "year", "rated" ]에 일치하는 결과를 출력할 수 있습니다.

db.movies.aggregate( [
{ $match: { rated: { $ne: null }, year: { $ne: null } } },
{ $group: {
_id: { year: "$year", rated: "$rated" },
movieCount: { $sum: 1 } } },
{ $project: { _id: 0, year: "$_id.year", rated: "$_id.rated",
movieCount: 1 } },
{ $merge: { into: "moviesByYearAndRating",
"on": [ "year", "rated" ], whenMatched: "replace",
whenNotMatched: "insert" } }
] )
[1] sh.shardCollection() 2} 메서드는 옵션을 전달할 때 샤드 { unique: true } 키가 범위 기반이고 , 컬렉션이 비어 있으며, 샤드 키의 고유 인덱스가 아직 존재하지 않는 경우 샤드 키에 고유 인덱스를 생성할 수도 있습니다. 이전 예시에서는 on 식별자가 샤드 키와 다른 필드이므로 해당 인덱스를 생성하기 위한 별도의 작업이 필요합니다.

$merge 집계 결과에 on 사양에 따라 일치하는 문서가 하나 이상 포함된 경우 출력 컬렉션의 기존 문서를 대체할 수 있습니다. 따라서 집계 결과에 컬렉션의 모든 기존 문서에 대해 일치하는 문서가 포함되어 있고 "replace"whenMatched에 지정하는 경우 $merge는 기존 컬렉션의 모든 문서를 대체할 수 있습니다.

그러나 집계 결과에 관계없이 기존 컬렉션을 바꾸려면 $out 대신 사용합니다.

$merge$merge 때문에 기존 문서의 _id 값이 변경되면 오류를 발생시킵니다.

이 오류를 방지하려면 on 필드에 _id 필드가 포함되지 않은 경우 집계 결과에서 _id 필드를 제거하여 이전 $unset 단계 등과 같이 오류를 방지합니다.

또한, 샤딩된 컬렉션의 경우 $merge 는 기존 문서의 샤드 키 값이 변경되는 경우에도 오류를 생성합니다.

오류가 발생하기 전에 $merge가 완료한 모든 쓰기는 롤백되지 않습니다.

on 필드에 대해 $merge가 사용하는 고유 인덱스가 집계 도중에 제거되는 경우 집계가 중단된다는 보장이 없습니다. 집계가 계속되면 문서에 중복된 on 필드 값이 없다는 보장이 없습니다.

$merge가 출력 컬렉션의 고유 인덱스를 위반하는 문서를 작성하려고 하면 작업이 오류를 생성합니다. 예시는 다음과 같습니다.

  • 온 필드의 인덱스가 아닌 고유 인덱스를 위반하는 일치하지 않는 문서를 삽입합니다 .

  • 컬렉션에 일치하는 문서가 있으면실패합니다. 즉, 이 작업은 on 필드의 고유 인덱스를 위반하는 일치하는 문서를 삽입하려고 시도합니다.

  • 기존 문서를 on 필드의 인덱스가 아닌 고유 인덱스를 위반하는 새 문서로 바꿉니다.

  • 일치하는 문서를 병합하면 필드의 인덱스가 아닌 고유 인덱스를 위반하는 문서가 생성됩니다.

컬렉션이 스키마 유효성 검사를 사용하고 validationActionerror로 설정된 경우, $merge로 잘못된 문서를 삽입하거나 잘못된 값으로 문서를 업데이트하면 MongoServerError가 발생하며, 문서는 대상 컬렉션에 기록되지 않습니다. 잘못된 문서가 여러 개 있는 경우, 처음으로 발견된 잘못된 문서만 오류를 발생시킵니다. 모든 유효한 문서는 대상 컬렉션에 기록되며 모든 잘못된 문서는 기록에 실패합니다.

$merge 단계에 대해 다음 사항이 모두 true인 경우에는 $merge가 문서를 출력 컬렉션에 직접 삽입합니다.

  • whenMatched의 값은 집계 파이프라인입니다,

  • whenNotMatched의 값은 insert입니다.

  • 출력 컬렉션에 일치하는 문서가 없습니다,

$merge 는 문서를 출력 컬렉션에 바로 삽입합니다.

$merge의 도입으로 MongoDB는 집계 파이프라인의 결과를 컬렉션에 기록하기 위한 두 단계인 $merge$out을 제공합니다.

$merge
  • 동일하거나 다른 데이터베이스의 컬렉션으로 출력할 수 있습니다.

  • 동일하거나 다른 데이터베이스의 컬렉션으로 출력할 수 있습니다.

  • 출력 컬렉션이 아직 존재하지 않는 경우 새 컬렉션을 생성합니다.

  • 출력 컬렉션이 아직 존재하지 않는 경우 새 컬렉션을 생성합니다.

  • 결과(새 문서 삽입, 문서 병합, 문서 교체, 기존 문서 유지, 작업 실패, 사용자 지정 업데이트 파이프라인으로 문서 처리)를 기존 컬렉션에 통합할 수 있습니다.

  • 출력 컬렉션이 이미 있는 경우 완전히 바꿉니다.

  • 샤드된 컬렉션으로 출력할 수 있습니다. 입력 컬렉션도 샤딩할 수 있습니다.

  • 출력 대상 컬렉션은 샤딩될 수 없습니다. 그러나 입력 컬렉션은 샤딩될 수 있습니다.

  • 다음 SQL 문에 해당합니다.

    • MERGE.

    • INSERT INTO T2 SELECT FROM T1.

    • SELECT INTO T2 FROM T1.

    • 머티리얼라이즈드 뷰 생성/새로 고침.

  • 다음 SQL 문에 해당합니다.

    • INSERT INTO T2 SELECT FROM T1.

    • SELECT INTO T2 FROM T1.

경고

$merge 집계 중인 동일한 컬렉션 에 출력이 발생하면 문서가 여러 번 업데이트되거나 작업이 무한 루프가 발생할 수 있습니다. 이 동작은 $merge 에서 수행한 업데이트로 인해 디스크에 저장된 문서의 물리적 위치 변경될 때 발생합니다. 문서 의 물리적 위치 변경되면 $merge 에서 문서를 완전히 새로운 문서 로 간주하여 추가 업데이트를 수행할 수 있습니다. 이 동작에 대한 자세한 내용은 '할로윈 문제'를 참조하세요.

$merge는 집계 중인 컬렉션과 동일한 컬렉션으로 출력할 수 있습니다. $lookup과 같이 파이프라인의 다른 단계에 나타나는 컬렉션으로 출력할 수도 있습니다.

제한 사항
설명

집계 파이프라인은 트랜잭션 내부에서 $merge를 사용할 수 없습니다.

집계 파이프라인은 $merge를 사용하여 time series 컬렉션으로 출력할 수 없습니다.

Separate from materialized view

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

$lookup 단계

$lookup 단계의 중첩된 파이프라인$merge 단계를 포함할 수 없습니다.

$facet 단계

$facet 단계의 중첩된 파이프라인$merge 단계를 포함할 수 없습니다.

$unionWith 단계

$unionWith 단계의 중첩된 파이프라인$merge 단계를 포함할 수 없습니다.

"linearizable" readConcern

$merge 단계는 읽기 고려 "linearizable"와 함께 사용할 수 없습니다. 즉, db.collection.aggregate()에 대해 "linearizable"의 읽기 고려를 지정하면 파이프라인에 $merge 단계를 포함할 수 없습니다.

이 페이지의 예시에서는 sample_mflix 샘플 데이터 세트의 데이터를 사용합니다. 이 데이터 세트를 자체 관리형 MongoDB 배포서버에 로드하는 방법에 대한 자세한 내용은 샘플 데이터 세트 로드를 참조하세요. 샘플 데이터베이스를 수정한 경우 이 페이지의 예시를 실행 하려면 데이터베이스를 제거하고 다시 만들어야 할 수 있습니다.

출력 컬렉션이 존재하지 않으면 $merge 가 컬렉션을 생성합니다.

참고

복제본 세트 또는 독립형 배포서버의 경우 출력 데이터베이스가 존재하지 않으면 $merge도 데이터베이스를 생성합니다.

샤딩된 클러스터 배포의 경우, 지정된 출력 데이터베이스가 이미 존재해야 합니다.

$group$merge 단계를 사용하여 개봉 연도 및 콘텐츠 등급별로 비평가들의 호평을 받은 영화를 요약한 movieRatingSummary 컬렉션을 만들 수 있습니다:

db.movies.aggregate( [
{ $match: { metacritic: 100, rated: { $ne: null },
year: { $lte: 1972 } } },
{ $group: { _id: { year: "$year", rated: "$rated" },
count: { $sum: 1 } } },
{ $merge : { into: "movieRatingSummary", on: "_id",
whenMatched: "replace", whenNotMatched: "insert" } }
] )

파이프라인은 다음 단계를 사용합니다:

  • $match 1972년까지 개봉한 영화 중 평단의 극찬을 받은 작품을 콘텐츠 등급과 함께 필터링하는 단계

  • $group 단계는 yearrated별로 영화를 그룹화합니다.

  • $merge 이전 $group 단계의 출력을 sample_mflix 데이터베이스의 movieRatingSummary 컬렉션에 씁니다.

movieRatingSummary 컬렉션의 문서를 보려면 다음과 같이 하세요:

db.movieRatingSummary.find().sort(
{ _id: 1 } )
[
{ _id: { year: 1939, rated: 'PASSED' }, count: 1 },
{ _id: { year: 1962, rated: 'PG' }, count: 1 },
{ _id: { year: 1963, rated: 'PG' }, count: 1 },
{ _id: { year: 1970, rated: 'R' }, count: 1 },
{ _id: { year: 1972, rated: 'R' }, count: 1 }
]

이 집계 파이프라인은 이전 예시의 movieRatingSummary 컬렉션을 업데이트하여 1963년 이후 비평가들의 호평을 받은 영화를 포함하기 위해 다음 단계를 사용합니다.

  • $match 단계로 이동하여 metacritic: 100, 콘텐츠 등급, 개봉 연도가 1963년 이후인 모든 영화를 찾습니다.

  • $group 단계를 사용하여 영화를 yearrated별로 그룹화합니다.

  • $merge 동일한 _id 값을 가진 문서를 대체하며, 결과 세트를 movieRatingSummary 컬렉션에 씁니다. 컬렉션에 일치하는 문서가 없는 문서의 경우 $merge가 새 문서를 삽입합니다.

db.movies.aggregate( [
{ $match: { metacritic: 100, rated: { $ne: null },
year: { $gte: 1963 } } },
{ $group: { _id: { year: "$year", rated: "$rated" },
count: { $sum: 1 } } },
{ $merge : { into: "movieRatingSummary", on: "_id",
whenMatched: "replace", whenNotMatched: "insert" } }
] )

집계가 실행된 후 movieRatingSummary 컬렉션의 문서를 확인합니다.

db.movieRatingSummary.find().sort(
{ _id: 1 } )
[
{ _id: { year: 1939, rated: 'PASSED' }, count: 1 },
{ _id: { year: 1962, rated: 'PG' }, count: 1 },
{ _id: { year: 1963, rated: 'PG' }, count: 1 },
{ _id: { year: 1970, rated: 'R' }, count: 1 },
{ _id: { year: 1972, rated: 'R' }, count: 1 },
{ _id: { year: 1982, rated: 'R' }, count: 1 },
{ _id: { year: 2014, rated: 'R' }, count: 1 }
]

$merge가 컬렉션의 기존 데이터를 덮어쓰지 않도록 하려면 whenMatchedkeepExisting 또는 fail로 설정합니다.

sample_mflix 데이터베이스의 컬렉션 movieArchive에는 평단의 찬사를 받은 영화들의 개봉 연도별 역사 기록이 포함되어 있습니다.

movieArchive 컬렉션에는 year 필드에 고유 인덱스가 있습니다. 릴리스 연도당 최대 하나의 레코드가 존재해야 합니다.

db.movieArchive.createIndex(
{ year: 1 }, { unique: true } )

이 집계 파이프라인은 1963 이후부터 평단의 극찬을 받은 영화를 포함하도록 movies 컬렉션의 데이터로 movieArchive 컬렉션을 업데이트합니다. 파이프라인은 다음 단계를 사용합니다:

  • $match 단계로 이동하여 콘텐츠 등급(metacritic: 100)이 있는 모든 영화와 year >= 1963을 찾습니다.

  • $group 단계는 year별로 영화 제목을 그룹화합니다.

  • $project 단계를 수행하여 _id 필드를 표시하지 않고 year를 최상위 필드로 승격시킵니다. 문서가 $merge로 전달되면 $merge는 문서에 대한 새 _id 필드를 자동으로 생성합니다.

  • $merge 결과 세트를 movieArchive에 기록합니다.

    $merge 단계는 year 필드있는 문서와 일치하며, 일치할 경우 실패합니다. 즉, 해당 출시 연도에 대한 문서가 이미 존재하면 $merge 오류가 발생합니다.

db.movies.aggregate( [
{ $match: { metacritic: 100, rated: { $ne: null },
year: { $gte: 1963 } } },
{ $group: { _id: "$year",
titles: { $push: "$title" } } },
{ $project: { _id: 0, year: "$_id", titles: 1 } },
{ $merge : { into: "movieArchive", on: "year",
whenMatched: "fail" } }
] )

만약 movieArchive 컬렉션이 1963~2014 사이의 어떤 연도에 대한 문서를 이미 포함하고 있다면, 집계 중복 키 오류로 인해 실패합니다. 그러나 파이프라인은 오류 발생 전에 삽입한 문서를 롤백하지 않습니다.

일치하는 문서에 대해 keepExisting을 지정하면 집계가 일치하는 문서에 영향을 주지 않고 중복 키 오류를 발생시키지 않습니다. 마찬가지로 replace를 지정해도 작업이 실패하지는 않지만 기존 문서가 대체됩니다.

기본적으로 집계 결과의 문서가 컬렉션의 문서와 일치하면 $merge 단계에서 문서가 병합됩니다.

$merge를 사용하여 movies 컬렉션과 comments 컬렉션의 결과를 병합하여 새 컬렉션 yearlyStats을 만들 수 있습니다.

yearlyStats 컬렉션을 생성하려면 다음 파이프라인을 실행합니다.

db.movies.aggregate( [
{ $match: { metacritic: 100, rated: { $ne: null },
year: { $gte: 1970, $lte: 1972 } } },
{ $group: { _id: "$year", movieCount: { $sum: 1 } } },
{ $merge : { into: "yearlyStats", on: "_id",
whenMatched: "merge", whenNotMatched: "insert" } }
])
첫 번째 단계:
$match 단계 필터는 평론가들의 극찬을 받은 영화(metacritic: 100) 중에서 콘텐츠 등급이 있는 작품으로, 1970~1972년 사이에 개봉한 영화입니다.
두 번째 단계:
$group 단계는 year별로 그룹화하고, 영화를 새로운 movieCount 필드에 집계합니다.
세 번째 단계:
$merge 단계에서는 동일한 데이터베이스의 yearlyStats 컬렉션에 문서를 씁니다. 해당 단계가 컬렉션에서 _id 필드와 일치하는 기존 문서를 찾으면 해당 단계는 일치하는 문서를 병합합니다. 그렇지 않으면 단계가 문서를 삽입합니다. 처음 생성할 때는 일치하는 문서가 없습니다.

컬렉션의 문서를 보려면 다음 작업을 실행합니다.

db.yearlyStats.find().sort( { _id: 1 } )
[
{ _id: 1970, movieCount: 1 },
{ _id: 1972, movieCount: 1 }
]

마찬가지로, comments 컬렉션에 대해 다음 집계 파이프라인을 실행하여 댓글 수를 yearlyStats 컬렉션에 병합합니다.

db.comments.aggregate( [
{ $match: { date: { $gte: new Date("1970-01-01"),
$lt: new Date("1973-01-01") } } },
{ $group: { _id: { $year: "$date" },
commentCount: { $sum: 1 } } },
{ $merge : { into: "yearlyStats", on: "_id",
whenMatched: "merge", whenNotMatched: "insert" } }
])
첫 번째 단계:
$match 단계에서 1970~1972년 사이에 게시된 댓글을 필터링합니다.
두 번째 단계:
$group 단계는 주석 date에서 추출한 연도를 기준으로 그룹화하고 주석을 새 commentCount 필드에 집계합니다.
세 번째 단계:
$merge 단계에서는 동일한 데이터베이스의 yearlyStats 컬렉션에 문서를 씁니다. 단계에서 _id 필드(년)에서 일치하는 기존 문서가 컬렉션에서 발견되면 단계에서 일치하는 문서를 병합합니다. 그렇지 않으면 단계가 문서를 삽입합니다.

데이터가 병합된 후 yearlyStats 컬렉션의 문서를 보려면 다음 작업을 실행하세요.

db.yearlyStats.find().sort( { _id: 1 } )
[
{ _id: 1970, movieCount: 1, commentCount: 889 },
{ _id: 1971, commentCount: 825 },
{ _id: 1972, movieCount: 1, commentCount: 863 }
]

$merge는 문서가 일치할 때 사용자 지정 업데이트 파이프라인을 사용할 수 있습니다. 언제 일치 파이프라인은 다음과 같은 단계를 가질 수 있습니다:

컬렉션 monthlyCommentTotals는 각 월별 댓글 수의 누적 합계를 추적합니다.

매일 새로운 댓글이 sample_mflix.comments 컬렉션에 도착합니다. 다음 집계 파이프라인은 해당 날짜의 댓글 수로 월별 합계를 업데이트합니다:

db.comments.aggregate([
{ $match: { date: { $gte: new Date("1970-01-15"),
$lt: new Date("1970-01-16") } } },
{ $group: { _id: { $dateToString: { format: "%Y-%m",
date: "$date" } }, count: { $sum: 1 } } },
{ $merge: {
into: "monthlyCommentTotals",
on: "_id",
whenMatched: [
{ $addFields: {
count: { $add: [ "$count", "$$new.count" ] }
} }
],
whenNotMatched: "insert"
} }
])
첫 번째 단계:
$match 단계는 1970년 1월 15일에 게시된 모든 댓글을 찾습니다.
두 번째 단계:
$group 단계에서는 일치하는 댓글을 연/월별로 그룹화하여 집계합니다.
세 번째 단계:

$merge 단계에서는 monthlyCommentTotals 컬렉션에 문서를 기록합니다. 단계가 _id 필드와 일치하는 컬렉션에서 기존 문서를 찾으면 파이프라인을 사용하여 기존 월별 합계에 해당일의 count를 더합니다.

  • 이 파이프라인은 결과 문서의 필드에 직접 액세스할 수 없습니다. 결과 문서의 count 필드에 접근하기 위해 파이프라인은 $$new 변수를 사용합니다, 즉 $$new.count.

  • 이 파이프라인은 컬렉션에 있는 기존 문서의 count 필드, 즉 $count에 직접 액세스할 수 있습니다.

결과 문서가 기존 문서를 대체합니다.

병합 작업 후 monthlyCommentTotals 컬렉션의 문서를 보려면 다음 작업을 실행하세요.

db.monthlyCommentTotals.find()
[ { _id: '1970-01', count: 71 } ]

whenMatched 필드에 $merge 단계의 변수를 사용할 수 있습니다. 변수를 사용하려면 먼저 변수를 정의해야 합니다.

다음 중 하나 또는 둘 모두에서 변수를 정의합니다:

때매치에서변수를 사용하려면:

변수 이름과 함께 이중 달러 기호 ($$) 접두사를 $$<variable_name> 형식으로 지정합니다. 예시: $$year. 변수가 문서로 설정된 경우 $$<variable_name>.<field> 형식으로 문서 필드를 포함할 수도 있습니다. 예시: $$year.month.

아래 탭은 병합 단계, 집계 명령 또는 둘 다에서 변수가 정의될 때의 동작을 보여줍니다.

$merge 단계 let에서 변수를 정의하고 whenMatched 필드에서 변수를 사용할 수 있습니다.

다음 예제입니다.

  • movies 컬렉션의 영화로 movieDetails 컬렉션을 초기화합니다.

  • #std-label-merge-letlet에서 year 변수를 정의하는 aggregate 명령을 실행하고 whenMatched를 사용하여 movieDetails에 연도를 추가합니다.

  • retrieves the movieDetails document

db.movies.aggregate( [
{ $match: { title: "The Godfather" } },
{ $limit: 1 },
{ $project: { title: 1 } },
{ $merge: { into: "movieDetails", whenNotMatched: "insert" } }
] )
db.runCommand( {
aggregate: db.movieDetails.getName(),
pipeline: [ {
$merge: {
into: db.movieDetails.getName(),
let : { year: "2023" },
whenMatched: [ {
$addFields: { "addedYear": "$$year" }
} ]
}
} ],
cursor: {}
} )
db.movieDetails.find()
[ { _id: ..., title: 'The Godfather', addedYear: '2023' } ]

버전 5.0에 추가.

aggregate 명령 let에서 변수를 정의하고 $merge 단계 whenMatched 필드에서 변수를 사용할 수 있습니다.

다음 예제입니다.

  • movies 컬렉션의 영화로 movieDetails 컬렉션을 초기화합니다.

  • aggregate 명령 let에서 year 변수를 정의하는 aggregate 명령을 실행하고 whenMatched를 사용하여 movieDetails에 연도를 추가합니다.

  • retrieves the movieDetails document

db.movies.aggregate( [
{ $match: { title: "The Godfather" } },
{ $limit: 1 },
{ $project: { title: 1 } },
{ $merge: { into: "movieDetails", whenNotMatched: "insert" } }
] )
db.runCommand( {
aggregate: db.movieDetails.getName(),
pipeline: [ {
$merge: {
into: db.movieDetails.getName(),
whenMatched: [ {
$addFields: { "addedYear": "$$year" }
} ]
}
} ],
cursor: {},
let : { year: "2023" }
} )
db.movieDetails.find()
[ { _id: ..., title: 'The Godfather', addedYear: '2023' } ]

$merge 단계에서 변수를 정의할 수 있으며 MongoDB 5.0부터는 aggregate 명령입니다.

동일한 이름을 가진 두 개의 변수가 $merge 단계와 aggregate 명령에 정의된 경우 $merge 단계 변수가 사용됩니다.

이 예시에서 파이프라인은 year: "2023"year: "2019" aggregate 명령 변수 대신 사용합니다.

db.movies.aggregate( [
{ $match: { title: "The Godfather" } },
{ $limit: 1 },
{ $project: { title: 1 } },
{ $merge: { into: "movieDetails", whenNotMatched: "insert" } }
] )
db.runCommand( {
aggregate: db.movieDetails.getName(),
pipeline: [ {
$merge: {
into: db.movieDetails.getName(),
let : { year: "2023" },
whenMatched: [ {
$addFields: { "addedYear": "$$year" }
} ]
}
} ],
cursor: {},
let : { year: "2019" }
} )
db.movieDetails.find()
[ { _id: ..., title: 'The Godfather', addedYear: '2023' } ]

다음 Movie 클래스는 이 예시 에 사용된 문서를 모델링합니다.

[BsonIgnoreExtraElements]
public class Movie
{
[BsonId]
public ObjectId Id { get; set; }
[BsonElement("title")]
public string Title { get; set; } = null!;
[BsonElement("year")]
public int? Year { get; set; }
[BsonElement("runtime")]
public int? Runtime { get; set; }
[BsonElement("rated")]
public string? Rated { get; set; }
[BsonElement("metacritic")]
public int Metacritic { get; set; }
[BsonElement("plot")]
public string? Plot { get; set; }
[BsonElement("type")]
public string? Type { get; set; }
[BsonElement("cast")]
public string[]? Cast { get; set; }
[BsonElement("directors")]
public string[]? Directors { get; set; }
[BsonElement("writers")]
public string[]? Writers { get; set; }
[BsonElement("imdb")]
public ImdbData? Imdb { get; set; }
}

MongoDB .NET/ C# 운전자 사용하여 $merge 집계 파이프라인 에 단계를 추가하려면 PipelineDefinition 객체 에서 Merge() 메서드를 호출합니다.

Merge() 메서드를 호출할 때는 MergeStageOptions 클래스의 인스턴스 전달해야 합니다. 이 객체 사용하면 일치하는 문서를 처리하다 방법과 같은 $merge 단계에 대한 옵션을 지정할 수 있습니다.

다음 예시 파이프 파이프라인 의 문서를 movies 컬렉션 에 병합하는 파이프라인 단계를 만듭니다. MergeStageOptions 객체 다음 옵션을 지정합니다.

  • OnFieldNames 옵션은 작업에서 "_id" 필드 사용하여 일치하는 문서를 식별하도록 지정합니다.

  • WhenMatched 옵션은 소스 컬렉션 의 문서 대상 컬렉션 의 문서 와 일치하는 경우 작업이 일치하는 문서 대체하도록 지정합니다.

  • WhenNotMatched 옵션은 소스 컬렉션 의 문서 대상 컬렉션 의 문서 일치하지 않는 경우 작업이 대상 컬렉션 에 문서 삽입하도록 지정합니다.

var pipeline = new EmptyPipelineDefinition<Movie>()
.Merge(_targetCollection,
new MergeStageOptions<Movie>()
{
OnFieldNames = new List<string>() { "_id" },
WhenMatched = MergeStageWhenMatched.Replace,
WhenNotMatched = MergeStageWhenNotMatched.Insert,
});
{ "_id": "...", "title": "Back to the Future", "metacritic": 96 }
{ "_id": "...", "title": "Jurassic Park", "metacritic": 68 }
{ "_id": "...", "title": "The Shawshank Redemption", "metacritic": 80 }

이 페이지의 Node.js 예제에서는 Atlas 샘플 데이터 세트sample_mflix 데이터베이스 사용합니다. 무료 MongoDB Atlas cluster 생성하고 샘플 데이터 세트를 로드하는 방법을 학습하려면 MongoDB Node.js 운전자 설명서에서 시작하기 를 참조하세요.

MongoDB Node.js 운전자 사용하여 집계 파이프라인 에 $merge 단계를 추가하려면 파이프라인 객체 에서 $merge 연산자 사용합니다.

다음 예시 파이프 파이프라인 의 문서를 movies 컬렉션 에 병합하는 파이프라인 단계를 만듭니다. 이 예시 에는 다음 필드가 포함되어 있습니다.

  • on 옵션은 작업이 "_id""title" 필드를 사용하여 소스 컬렉션 과 movies 컬렉션 에서 일치하는 문서를 찾도록 지정합니다.

  • whenMatched 옵션은 소스 컬렉션 의 문서 movies 컬렉션 의 문서 와 일치하는 경우 movies 컬렉션 의 문서 대체하도록 지정합니다.

  • whenNotMatched 옵션은 소스 컬렉션 의 문서 movies 컬렉션 의 문서 와 일치하지 않는 경우 작업이 movies 컬렉션 에 문서 삽입하도록 지정합니다.

그런 다음 이 예시 에서는 집계 파이프라인 실행합니다.

const pipeline = [
{
$merge: {
into: "movies",
on: ["_id", "title"],
whenMatched: "replace",
whenNotMatched: "insert"
}
}
];
const cursor = collection.aggregate(pipeline);
return cursor;

돌아가기

$매치

이 페이지의 내용