AI 에이전트의 경우: 문서 인덱스는 https://www.mongodb.com/ko-kr/docs/llms.txt에서 사용할 수 있으며, 모든 페이지의 마크다운 버전은 어떤 URL 경로에 .md를 추가하여 사용할 수 있습니다.
Docs Menu

$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" ]

    배열의 필드 순서는 중요하지 않으며 동일한 필드를 여러 번 지정할 수 없습니다.

지정된 필드에 대해

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

  • MongoDB 8.0 이전 버전 실행 on 배포서버의 경우 에 지정된 8.1 필드 누락되거나 null 값을 포함할 수 없습니다. MongoDB 부터 지원 인덱스 희소가 아닌 경우 에 지정된 필드 on 가 누락되거나 null 값이 포함될 수 있습니다.

  • 지정된 필드 는 배열 값을 포함할 수 없습니다.

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

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

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

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

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

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

  • 출력 컬렉션이 없으면 on 식별자는 _id 필드여야 하며 기본값은 _id 필드입니다. 해당 고유 _id 인덱스가 자동으로 생성됩니다.

    • 존재하지 않는 컬렉션에 대해 다른 on 식별자 필드를 사용하려면 먼저 원하는 필드에 고유 인덱스를 만들어 컬렉션을 생성할 수 있습니다. 예를 보려면 존재하지 않는 출력 수집 섹션을 참조하세요.

    • MongoDB 8.3부터 서버 자동으로 생성된 _id 인덱스 쿼리의 데이터 정렬과 일치하는지 확인합니다. 데이터 정렬이 일치하지 않으면 _id 인덱스 쿼리 에 고유성을 제공할 수 없으며 쿼리 실행 되지 않습니다.

  • 기존 출력 컬렉션이 샤딩 해제된 경우 on 식별자는 기본적으로 _id 필드로 설정됩니다.

  • 기존 출력 컬렉션이 샤드된 컬렉션인 경우 on 식별자는 기본적으로 모든 샤드 키 필드와 _id 필드로 설정됩니다. 다른 on 식별자를 지정하는 경우 on에는 모든 샤드 키 필드가 포함되어야 합니다.

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

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

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

    작업
    설명

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

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

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

    기존 문서는 출력 컬렉션에 그대로 유지합니다.

    "merge"(기본값)

    일치하는 문서를 병합합니다($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>입니다. $$new 변수는 let 지정이 생략된 경우에만 사용할 수 있습니다.

    • 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"(기본값)

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

문서를 삭제합니다. 특히 $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() 메서드는 { 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 다음 모든 조건이 참일 경우 문서를 출력 컬렉션에 직접 삽입합니다.

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

  • whenNotMatched 의 값은 insert입니다.

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

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

$merge
  • 동일하거나 다른 데이터베이스의 컬렉션으로 출력할 수 있습니다.
  • 동일하거나 다른 데이터베이스의 컬렉션으로 출력할 수 있습니다.
  • 출력 컬렉션이 아직 존재하지 않는 경우 새 컬렉션을 생성합니다.
  • 출력 컬렉션이 아직 존재하지 않는 경우 새 컬렉션을 생성합니다.
  • 결과(새 문서 삽입, 문서 병합, 문서 교체, 기존 문서 유지, 작업 실패, 사용자 지정 업데이트 파이프라인으로 문서 처리)를 기존 컬렉션에 통합할 수 있습니다.

    문서 바꾸기($merge) 대 컬렉션 바꾸기($out)도 참조하세요.

  • 출력 컬렉션이 이미 있는 경우 완전히 바꿉니다.
  • 샤드된 컬렉션으로 출력할 수 있습니다. 입력 컬렉션도 샤딩할 수 있습니다.
  • 출력 대상 컬렉션은 샤딩될 수 없습니다. 그러나 입력 컬렉션은 샤딩될 수 있습니다.
  • 다음 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 컬렉션으로 출력할 수 없습니다.

보기 정의
구체화된 뷰에서 분리

뷰 정의에는 $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 객체 에서 UnionWith() 메서드를 호출합니다.

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;