db.collection.findOneAndUpdate()
정의
db.collection.findOneAndUpdate( filter, update, options )
중요
Mongo쉬 방법
이 페이지에서는
mongosh
메서드를 설명합니다. 이는 데이터베이스 명령 또는 Node.js와 같은 언어별 드라이버에 대한 설명서가 아닙니다.데이터베이스 명령의 경우
update
명령을 참조하세요.MongoDB API 드라이버의 경우 언어별 MongoDB 드라이버 설명서를 참조하세요.
filter
및sort
기준에 따라 단일 문서를 업데이트합니다.반환합니다: 기본적으로 원본 문서를 반환합니다. returnNewDocument가 true
로 설정되거나 returnDocument가after
로 설정된 경우 업데이트된 문서를 반환합니다.
호환성
다음 환경에서 호스팅되는 배포에 db.collection.findOneAndUpdate()
사용할 수 있습니다.
MongoDB Atlas: 클라우드에서의 MongoDB 배포를 위한 완전 관리형 서비스
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 | 유형 | 설명 | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
filter | 문서 | |||||||||||||||||||
update | 문서 또는 배열 | 업데이트 문서 또는 집계 파이프라인
| ||||||||||||||||||
writeConcern | 문서 | 선택 사항입니다. 쓰기 고려를 표현하는 문서입니다. 기본 쓰기 고려를 사용하지 않으려면 생략하세요.
트랜잭션에서 실행되는 경우 작업에 대한 쓰기 고려를 명시적으로 설정하지 마세요. 트랜잭션에 쓰기 고려를 사용하려면 트랜잭션 및 쓰기 고려를 참조하세요. | ||||||||||||||||||
projection | 문서 | 선택 사항. 반환할 필드의 하위 집합입니다. 일치하는 문서의 모든 필드를 반환하려면 이 매개 변수를 생략하세요. 프로젝션 인수가 문서가 아닌 경우 작업 오류가 발생합니다. | ||||||||||||||||||
sort | 문서 | |||||||||||||||||||
maxTimeMS | 숫자 | 선택 사항. 작업을 완료해야 하는 시간 제한을 밀리초 단위로 지정합니다. 제한을 초과하면 오류를 반환합니다. | ||||||||||||||||||
upsert | 부울 | 선택 사항입니다.
여러 개의 업서트를 방지하려면 기본값은 | ||||||||||||||||||
returnDocument | 문자열 | 선택 사항입니다.
| ||||||||||||||||||
returnNewDocument | 부울 | 선택 사항. 기본값은 | ||||||||||||||||||
collation | 문서 | 선택 사항. 작업에 사용할 데이터 정렬을 지정합니다. 데이터 정렬을 사용하면 대소문자 및 악센트 표시 규칙과 같은 문자열 비교에 대한 언어별 규칙을 지정할 수 있습니다. 데이터 정렬 옵션의 구문은 다음과 같습니다:
데이터 정렬을 지정할 때 데이터 정렬이 지정되지 않았지만 컬렉션에 기본 데이터 정렬이 있는 경우( 컬렉션 또는 연산에 대한 데이터 정렬이 지정되지 않은 경우, MongoDB는 이전 버전에서 문자열 비교에 사용된 간단한 이진 비교를 사용합니다. 한 연산에 대해 여러 데이터 정렬을 지정할 수 없습니다. 예를 들어 필드별로 서로 다른 데이터 정렬을 지정할 수 없으며 정렬과 함께 찾기를 수행하는 경우 찾기 와 정렬에서 각각 다른 데이터 정렬을 사용하는 것은 허용되지 않습니다. | ||||||||||||||||||
arrayFilters | 배열 | 선택 사항입니다. 필터 문서의 배열로, 배열 필드에 대한 업데이트 작업을 위해 수정할 배열 요소를 결정합니다. 업데이트 문서에서
업데이트 문서에 동일한 식별자를 여러 번 포함할 수 있지만, 업데이트 문서의 각 고유 식별자(
그러나 다음 예시와 같이 단일 필터 문서에서 동일한 식별자에 복합 조건을 지정할 수 있습니다.
예시는
|
행동
문서 일치
db.collection.findOneAndUpdate()
는 filter
와 일치하는 컬렉션의 첫 번째 일치 문서를 업데이트합니다. filter
와 일치하는 문서가 없으면 문서가 업데이트되지 않습니다.
sort
매개변수는 어떤 문서가 업데이트될지에 영향을 줄 수 있습니다.
프로젝션
중요
언어 일관성
find()
및 findAndModify()
프로젝션을 집계의 $project
단계와 일치시키는 작업의 일환으로,
find()
및 프로젝션은 집계 표현식findAndModify()
및 구문을 사용할 수 있습니다.MongoDB는 프로젝션과 관련하여 추가 제한 사항을 시행합니다. 자세한 내용은 프로젝션 제한 사항을 참조하세요.
projection
매개변수는 다음 형식의 문서를 사용합니다.
{ field1 : <value>, field2 : <value> ... }
프로젝션 | 설명 |
---|---|
<field>: <1 or true> | 필드 포함 여부를 지정합니다. 프로젝션 값에 0이 아닌 정수를 지정하면 연산은 해당 값을 true 로 취급합니다. |
<field>: <0 or false> | 필드 제외 여부를 지정합니다. |
"<field>.$": <1 or true> | |
<field>: <array projection> | 배열 프로젝션 연산자( 뷰에는 사용할 수 없습니다. |
<field>: <aggregation expression> | 프로젝션된 필드의 값을 지정합니다. 리터럴 및 집계 변수 사용을 포함한 집계 식 및 구문을 사용하면 새 필드를 프로젝션하거나 기존 필드를 새 값으로 프로젝션할 수 있습니다.
|
임베디드 필드 지정
내장된 문서의 필드에 대해서는 다음 둘 중 하나를 사용하여 필드를 지정할 수 있습니다.
점 표기법(예시:
"field.nestedfield": <value>
중첩된 양식, 예를 들어
{ field: { nestedfield: <value> } }
_id
필드 프로젝션
필드를 표시하지 않기 위해 프로젝션에서 _id: 0
을 명시적으로 지정하지 않는 한 _id
필드는 기본적으로 반환된 문서에 포함됩니다.
포함 또는 제외
projection
필드는 포함과 제외 사양을 모두 포함할 수 없습니다. 단, _id
필드는 예외입니다.
필드를 명시적으로 포함하는 프로젝션에서
_id
필드는 명시적으로 제외할 수 있는 유일한 필드입니다.필드를 명시적으로 제외하는 프로젝션에서는
_id
필드가 명시적으로 포함할 수 있는 유일한 필드이지만,_id
필드는 기본적으로 포함됩니다.
프로젝션에 대한 자세한 내용은 다음 섹션도 같이 참조하세요.
샤드 컬렉션
샤딩된 컬렉션에서 db.collection.findOneAndUpdate()
를 사용하려면 쿼리 필터에 샤드 키에 대한 동일성 조건이 포함되어야 합니다.
샤딩된 컬렉션의 문서에는 샤드 키 필드가 누락될 수 있습니다. 샤드 키가 누락된 문서를 대상으로 하려면 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 }