db.collection.findOneAndUpdate()
드라이버가 포함된 MongoDB
이 페이지에서는 mongosh
메서드를 설명합니다. MongoDB 드라이버에서 해당 메서드를 보려면 프로그래밍 언어의 해당 페이지를 참조하세요.
정의
db.collection.findOneAndUpdate( filter, update, options )
filter
및sort
기준에 따라 단일 문서를 업데이트합니다.팁
8.0버전의 새로운 기능:
updateOne()
메서드에는 사용자가 지정한 정렬 순서로 첫 번째 문서를 업데이트하는sort
옵션이 포함되어 있습니다.반환합니다: 기본적으로 원본 문서를 반환합니다. returnNewDocument가 true
로 설정되거나 returnDocument가after
로 설정된 경우 업데이트된 문서를 반환합니다.
호환성
이 메서드는 다음 환경에서 호스팅되는 배포에서 사용할 수 있습니다.
MongoDB Atlas: 클라우드에서의 MongoDB 배포를 위한 완전 관리형 서비스
참고
이 명령은 모든 MongoDB Atlas 클러스터에서 지원됩니다. 모든 명령에 대한 Atlas 지원에 관해 자세히 알아보려면 지원되지 않는 명령을 참조하십시오.
MongoDB Enterprise: MongoDB의 구독 기반 자체 관리 버전
MongoDB Community: MongoDB의 소스 사용 가능 무료 자체 관리 버전
구문
findOneAndUpdate()
메서드의 형식은 다음과 같습니다.
db.collection.findOneAndUpdate( <filter>, <update document or aggregation pipeline>, { writeConcern: <document>, projection: <document>, sort: <document>, maxTimeMS: <number>, upsert: <boolean>, returnDocument: <string>, returnNewDocument: <boolean>, collation: <document>, arrayFilters: [ <filterdocument1>, ... ] } )
findOneAndUpdate()
메서드는 다음 매개변수를 사용합니다.
Parameter | 유형 | 설명 | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 문서 | |||||||||||||||||||
| 문서 또는 배열 | 업데이트 문서 또는 집계 파이프라인
| ||||||||||||||||||
| 문서 | 선택 사항입니다. 쓰기 고려를 표현하는 문서입니다. 기본 쓰기 고려를 사용하지 않으려면 생략하세요.
트랜잭션에서 실행되는 경우 작업에 대한 쓰기 고려를 명시적으로 설정하지 마세요. 트랜잭션에 쓰기 고려를 사용하려면 트랜잭션 및 쓰기 고려를 참조하세요. | ||||||||||||||||||
| 문서 | 선택 사항. 반환할 필드의 하위 집합입니다. 일치하는 문서의 모든 필드를 반환하려면 이 매개 변수를 생략하세요. 프로젝션 인수가 문서가 아닌 경우 작업 오류가 발생합니다. | ||||||||||||||||||
| 문서 | |||||||||||||||||||
| 숫자 | 선택 사항. 작업을 완료해야 하는 시간 제한을 밀리초 단위로 지정합니다. 제한을 초과하면 오류를 반환합니다. | ||||||||||||||||||
| 부울 | 선택 사항.
여러 개의 업서트를 방지하려면 기본값은 | ||||||||||||||||||
| 문자열 | 선택 사항입니다.
| ||||||||||||||||||
| 부울 | 선택 사항. 기본값은 | ||||||||||||||||||
| 문서 | 선택 사항. 작업에 사용할 데이터 정렬을 지정합니다. 데이터 정렬을 사용하면 대소문자 및 악센트 표시 규칙과 같은 문자열 비교에 대한 언어별 규칙을 지정할 수 있습니다. 데이터 정렬 옵션의 구문은 다음과 같습니다:
데이터 정렬을 지정할 때 데이터 정렬이 지정되지 않았지만 컬렉션에 기본 데이터 정렬이 있는 경우( 컬렉션 또는 연산에 대한 데이터 정렬이 지정되지 않은 경우, MongoDB는 이전 버전에서 문자열 비교에 사용된 간단한 이진 비교를 사용합니다. 한 연산에 대해 여러 데이터 정렬을 지정할 수 없습니다. 예를 들어 필드별로 서로 다른 데이터 정렬을 지정할 수 없으며 정렬과 함께 찾기를 수행하는 경우 찾기 와 정렬에서 각각 다른 데이터 정렬을 사용하는 것은 허용되지 않습니다. | ||||||||||||||||||
| 배열 | 선택 사항입니다. 필터 문서의 배열로, 배열 필드에 대한 업데이트 작업을 위해 수정할 배열 요소를 결정합니다. 업데이트 문서에서
업데이트 문서에 동일한 식별자를 여러 번 포함할 수 있지만, 업데이트 문서의 각 고유 식별자(
그러나 다음 예시와 같이 단일 필터 문서에서 동일한 식별자에 복합 조건을 지정할 수 있습니다.
예제는 를 사용한 배열 업데이트 작업을 참조하세요.
|
행동
성능
재시도 가능한 쓰기는 findOneAndUpdate()
메서드를 필요로 하며 업데이트를 수행하기 전에 복제본 세트의 각 노드에 대해 전체 문서를 특수 사이드 컬렉션으로 복사합니다. 이로 인해 대용량 문서나 대규모 복제 세트를 처리할 때 findOneAndUpdate()
작업에 많은 비용이 들 수 있습니다.
8.0 버전의 새로운 기능: 사용자 정의 정렬에서 첫 번째 문서를 더 나은 성능으로 업데이트하려면 sort
옵션과 함께 db.collection.updateOne()
메서드를 사용하세요.
문서 일치
db.collection.findOneAndUpdate()
는 filter
와 일치하는 컬렉션의 첫 번째 일치 문서를 업데이트합니다. filter
와 일치하는 문서가 없으면 문서가 업데이트되지 않습니다.
sort
매개변수는 어떤 문서가 업데이트될지에 영향을 줄 수 있습니다.
프로젝션
중요
언어 일관성
find()
및 findAndModify()
프로젝션을 집계의 $project
단계와 일치시키는 작업의 일환으로,
find()
및 프로젝션은 집계 표현식findAndModify()
및 구문을 사용할 수 있습니다.MongoDB는 프로젝션과 관련하여 추가 제한 사항을 시행합니다. 자세한 내용은 프로젝션 제한 사항을 참조하세요.
projection
매개변수는 다음 형식의 문서를 사용합니다.
{ field1 : <value>, field2 : <value> ... }
프로젝션 | 설명 |
---|---|
| 필드 포함 여부를 지정합니다. 프로젝션 값에 0이 아닌 정수를 지정하면 연산은 해당 값을 |
| 필드 제외 여부를 지정합니다. |
| |
| 배열 프로젝션 연산자( 뷰에는 사용할 수 없습니다. |
| 프로젝션된 필드의 값을 지정합니다. 리터럴 및 집계 변수 사용을 포함한 집계 식 및 구문을 사용하면 새 필드를 프로젝션하거나 기존 필드를 새 값으로 프로젝션할 수 있습니다.
|
임베디드 필드 지정
내장된 문서의 필드에 대해서는 다음 둘 중 하나를 사용하여 필드를 지정할 수 있습니다.
점 표기법(예시:
"field.nestedfield": <value>
중첩된 양식, 예를 들어
{ field: { nestedfield: <value> } }
_id
필드 프로젝션
필드를 표시하지 않기 위해 프로젝션에서 _id: 0
을 명시적으로 지정하지 않는 한 _id
필드는 기본적으로 반환된 문서에 포함됩니다.
포함 또는 제외
projection
필드는 포함과 제외 사양을 모두 포함할 수 없습니다. 단, _id
필드는 예외입니다.
필드를 명시적으로 포함하는 프로젝션에서
_id
필드는 명시적으로 제외할 수 있는 유일한 필드입니다.필드를 명시적으로 제외하는 프로젝션에서는
_id
필드가 명시적으로 포함할 수 있는 유일한 필드이지만,_id
필드는 기본적으로 포함됩니다.
프로젝션에 대한 자세한 내용은 다음 섹션도 같이 참조하세요.
샤드 컬렉션
샤딩된 컬렉션의 문서에는 샤드 키 필드가 누락될 수 있습니다. 샤드 키가 누락된 문서를 대상으로 하려면 null
동등성 매치를 다른 필터 조건(예: _id
필드)과 함께 사용할 수 있습니다. 예를 들면 다음과 같습니다.
{ _id: <value>, <shardkeyfield>: null } // _id of the document missing shard key
샤드 키 수정
샤드 키 필드가 변경할 수 없는 _id
필드가 아닌 경우 문서의 샤드 키 값을 업데이트할 수 있습니다.
경고
샤딩된 컬렉션의 문서에는 샤드 키 필드가 누락될 수 있습니다. 문서의 샤드 키 값을 변경할 때 실수로 샤드 키를 제거하지 않도록 주의해야 합니다.
기존 샤드 키 값을 db.collection.findOneAndUpdate()
으로 수정하려면 다음을 수행합니다.
누락된 샤드 키
샤딩된 컬렉션의 문서에는 샤드 키 필드가 누락 될 수 있습니다. db.collection.findOneAndUpdate()
를 사용하여 문서의 누락된 샤드 키를 설정하려면 다음을 수행해야 합니다.
반드시
mongos
에서 실행해야 합니다. 샤드에서 직접 작업을 실행하지 않아야 합니다.전체 샤드 키에 동등성 필터를 포함시켜야 합니다.
팁
누락된 키 값은 null 동등성 매치의 일부로 반환되므로 null 값 키가 업데이트되지 않도록 하려면 추가 쿼리 조건(예: _id
필드)을 적절히 포함하세요.
다음도 참조하세요.
트랜잭션
db.collection.findOneAndUpdate()
는 분산 트랜잭션 내에서 사용할 수 있습니다.
중요
대부분의 경우 분산 트랜잭션은 단일 문서 쓰기에 비해 더 큰 성능 비용이 발생하므로 분산 트랜잭션의 가용성이 효과적인 스키마 설계를 대체할 수는 없습니다. 대부분의 시나리오에서 비정규화된 데이터 모델 (내장된 문서 및 배열) 은 계속해서 데이터 및 사용 사례에 최적일 것입니다. 즉, 대부분의 시나리오에서 데이터를 적절하게 모델링하면 분산 트랜잭션의 필요성이 최소화됩니다.
추가 트랜잭션 사용 고려 사항(예: 런타임 제한 및 oplog 크기 제한)은 프로덕션 고려사항을 참조하세요.
트랜잭션 내 업서트
트랜잭션이 교차 샤드 쓰기 트랜잭션(write transaction)이 아닌 경우 분산 트랜잭션 내에서 컬렉션과 인덱스를 생성할 수 있습니다.
upsert: true
인 db.collection.findOneAndUpdate()
는 기존 컬렉션이나 존재하지 않는 컬렉션에서 실행될 수 있습니다. 존재하지 않는 컬렉션에서 실행하면 작업이 컬렉션을 만듭니다.
쓰기 고려 및 트랜잭션
트랜잭션에서 실행되는 경우 작업에 대한 쓰기 고려를 명시적으로 설정하지 마세요. 트랜잭션에 쓰기 고려를 사용하려면 트랜잭션 및 쓰기 고려를 참조하세요.
oplog 항목
db.collection.findOneAndUpdate()
작업이 문서를 성공적으로 업데이트하면 이 작업은 oplog(작업 로그)에 항목을 추가합니다. 작업이 실패하거나 업데이트할 문서를 찾지 못하면 작업은 oplog에 항목을 추가하지 않습니다.
예시
문서 업데이트
grades
컬렉션에는 다음과 유사한 문서가 포함되어 있습니다.
{ _id: 6305, name : "A. MacDyver", "assignment" : 5, "points" : 24 }, { _id: 6308, name : "B. Batlock", "assignment" : 3, "points" : 22 }, { _id: 6312, name : "M. Tagnum", "assignment" : 5, "points" : 30 }, { _id: 6319, name : "R. Stiles", "assignment" : 2, "points" : 12 }, { _id: 6322, name : "A. MacDyver", "assignment" : 2, "points" : 14 }, { _id: 6234, name : "R. Stiles", "assignment" : 1, "points" : 10 }
다음 작업은 name : R. Stiles
있는 첫 번째 문서를 찾고 점수를 5
씩 증가시킵니다.
db.grades.findOneAndUpdate( { "name" : "R. Stiles" }, { $inc: { "points" : 5 } } )
이 작업은 업데이트 전의 원본 문서를 반환합니다.
{ _id: 6319, name: "R. Stiles", "assignment" : 2, "points" : 12 }
returnNewDocument
이 참이면 업데이트된 문서를 반환하는 대신 작업을 수행합니다.
문서 정렬 및 업데이트
grades
컬렉션에는 다음과 유사한 문서가 포함되어 있습니다.
{ _id: 6305, name : "A. MacDyver", "assignment" : 5, "points" : 24 }, { _id: 6308, name : "B. Batlock", "assignment" : 3, "points" : 22 }, { _id: 6312, name : "M. Tagnum", "assignment" : 5, "points" : 30 }, { _id: 6319, name : "R. Stiles", "assignment" : 2, "points" : 12 }, { _id: 6322, name : "A. MacDyver", "assignment" : 2, "points" : 14 }, { _id: 6234, name : "R. Stiles", "assignment" : 1, "points" : 10 }
다음 작업은 name : "A. MacDyver"
이 있는 문서를 업데이트합니다. 이 작업은 일치하는 문서를 points
오름차순으로 정렬하여 일치하는 문서를 최소 포인트로 업데이트합니다.
db.grades.findOneAndUpdate( { "name" : "A. MacDyver" }, { $inc : { "points" : 5 } }, { sort : { "points" : 1 } } )
이 작업은 업데이트 전의 원본 문서를 반환합니다.
{ _id: 6322, name: "A. MacDyver", "assignment" : 2, "points" : 14 }
반환된 문서 프로젝트
다음 작업은 프로젝션을 사용하여 반환된 문서의 _id
, points
및 assignment
필드만 표시합니다.
db.grades.findOneAndUpdate( { "name" : "A. MacDyver" }, { $inc : { "points" : 5 } }, { sort : { "points" : 1 }, projection: { "assignment" : 1, "points" : 1 } } )
이 작업은 projection
문서에 지정된 필드만 있는 원본 문서와 투영 문서에서명시적으로 억제되지 않은(_id: 0
) _id
필드가 있는 원본 문서를 반환합니다.
{ "_id" : 6322, "assignment" : 2, "points" : 14 }
시간 제한이 있는 문서 업데이트
다음 작업은 삭제를 완료하는 데 5ms의 시간 제한을 설정합니다.
try { db.grades.findOneAndUpdate( { "name" : "A. MacDyver" }, { $inc : { "points" : 5 } }, { sort: { "points" : 1 }, maxTimeMS : 5 }; ); } catch(e){ print(e); }
작업이 시간 제한을 초과하면 작업은 다음을 반환합니다.
Error: findAndModifyFailed failed: { "ok" : 0, "errmsg" : "operation exceeded time limit", "code" : 50 }
업서트로 문서 업데이트
다음 작업은 filter
과 일치하는 항목이 없는 경우 upsert
필드를 사용하여 업데이트 문서를 삽입합니다.
try { db.grades.findOneAndUpdate( { "name" : "A.B. Abracus" }, { $set: { "name" : "A.B. Abracus", "assignment" : 5}, $inc : { "points" : 5 } }, { sort: { "points" : 1 }, upsert:true, returnNewDocument : true } ); } catch (e){ print(e); }
이 연산은 다음을 반환합니다:
{ "_id" : ObjectId("5789249f1c49e39a8adc479a"), "name" : "A.B. Abracus", "assignment" : 5, "points" : 5 }
returnNewDocument
를 설정한 경우 반환할 원본 문서가 없기 때문에 이 작업은 null
을 반환합니다.
데이터 정렬 지정
데이터 정렬을 사용하면 대소문자 및 악센트 표시 규칙과 같은 문자열 비교에 대한 언어별 규칙을 지정할 수 있습니다.
컬렉션 myColl
에는 다음 문서가 있습니다.
{ _id: 1, category: "café", status: "A" } { _id: 2, category: "cafe", status: "a" } { _id: 3, category: "cafE", status: "a" }
다음 작업에는 데이터 정렬 옵션이 포함됩니다.
db.myColl.findOneAndUpdate( { category: "cafe" }, { $set: { status: "Updated" } }, { collation: { locale: "fr", strength: 1 } } );
연산은 다음 문서를 반환합니다.
{ "_id" : 1, "category" : "café", "status" : "A" }
다음 값을 이용한 배열 업데이트 연산 arrayFilters
참고
arrayFilters
은 집계 파이프라인을 사용하는 업데이트에는 사용할 수 없습니다.
배열 필드를 업데이트할 때 업데이트할 배열 요소를 결정하는 arrayFilters
를 지정할 수 있습니다.
업데이트 요소가 arrayFilters
기준과 일치함
참고
arrayFilters
은 집계 파이프라인을 사용하는 업데이트에는 사용할 수 없습니다.
다음 문서를 사용하여 컬렉션 students
를 생성합니다.
db.students.insertMany( [ { "_id" : 1, "grades" : [ 95, 92, 90 ] }, { "_id" : 2, "grades" : [ 98, 100, 102 ] }, { "_id" : 3, "grades" : [ 95, 110, 100 ] } ] )
grades
배열에서 100
보다 크거나 같은 모든 요소를 수정하려면 db.collection.findOneAndUpdate()
메서드의 arrayFilters
옵션과 함께 필터링된 위치 연산자 $[<identifier>]
를 사용합니다.
db.students.findOneAndUpdate( { grades: { $gte: 100 } }, { $set: { "grades.$[element]" : 100 } }, { arrayFilters: [ { "element": { $gte: 100 } } ] } )
이 연산은 단일 문서의 grades
필드를 업데이트합니다. 연산이 완료된 후 컬렉션에 포함되는 문서는 다음과 같습니다.
{ "_id" : 1, "grades" : [ 95, 92, 90 ] } { "_id" : 2, "grades" : [ 98, 100, 100 ] } { "_id" : 3, "grades" : [ 95, 110, 100 ] }
문서 배열의 특정 요소 업데이트
참고
arrayFilters
은 집계 파이프라인을 사용하는 업데이트에는 사용할 수 없습니다.
다음 문서를 사용하여 컬렉션 students2
를 생성합니다.
db.students2.insertMany( [ { "_id" : 1, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 90, "std" : 4 }, { "grade" : 85, "mean" : 85, "std" : 6 } ] }, { "_id" : 2, "grades" : [ { "grade" : 90, "mean" : 75, "std" : 6 }, { "grade" : 87, "mean" : 90, "std" : 3 }, { "grade" : 85, "mean" : 85, "std" : 4 } ] } ] )
다음 연산은 _id
필드가 1
인 문서를 찾고, arrayFilters
(으)로 필터링된 위치 연산자 $[<identifier>]
을(를) 사용하여 성적이 85
와 같거나 더 큰 grades
배열 내 모든 요소의 mean
을(를) 수정합니다.
db.students2.findOneAndUpdate( { _id : 1 }, { $set: { "grades.$[elem].mean" : 100 } }, { arrayFilters: [ { "elem.grade": { $gte: 85 } } ] } )
이 연산은 단일 문서의 grades
필드를 업데이트합니다. 연산이 완료된 후 컬렉션에 포함되는 문서는 다음과 같습니다.
{ "_id" : 1, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 100, "std" : 4 }, { "grade" : 85, "mean" : 100, "std" : 6 } ] } { "_id" : 2, "grades" : [ { "grade" : 90, "mean" : 75, "std" : 6 }, { "grade" : 87, "mean" : 90, "std" : 3 }, { "grade" : 85, "mean" : 85, "std" : 4 } ] }
업데이트에 집계 파이프라인 사용하기
db.collection.findOneAndUpdate()
업데이트를 위한 집계 파이프라인을 수락할 수 있습니다. 파이프라인은 다음 단계로 구성될 수 있습니다.
$addFields
및 그 별칭$set
$replaceRoot
및 별칭$replaceWith
입니다.
집계 파이프라인e을 사용하면 현재 필드 값을 기반으로 조건부 업데이트를 표현하거나 다른 필드의 값을 사용하여 한 필드를 업데이트하는 등 보다 표현력이 풍부한 업데이트 구문을 작성할 수 있습니다.
그 예로 다음 문서를 사용해 students2
컬렉션을 생성하세요.
db.students2.insertMany( [ { "_id" : 1, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 90, "std" : 4 }, { "grade" : 85, "mean" : 85, "std" : 6 } ] }, { "_id" : 2, "grades" : [ { "grade" : 90, "mean" : 75, "std" : 6 }, { "grade" : 87, "mean" : 90, "std" : 3 }, { "grade" : 85, "mean" : 85, "std" : 4 } ] } ] )
다음 연산은 _id
필드가 1
인 문서를 찾고, 집계 파이프라인을 사용하여 grades
필드에서 새 필드 total
을(를) 계산합니다.
db.students2.findOneAndUpdate( { _id : 1 }, [ { $set: { "total" : { $sum: "$grades.grade" } } } ], // The $set stage is an alias for ``$addFields`` stage { returnNewDocument: true } )
이 작업은 업데이트된 문서를 반환합니다.
{ "_id" : 1, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 90, "std" : 4 }, { "grade" : 85, "mean" :85, "std" : 6 } ], "total" : 250 }