업데이트, 원자적 연산, 삭제
1. 도큐먼트 업데이트
- MongoDB의 도큐먼트 업데이트 방법
- 도큐먼트 전체 대치
- 업데이트 연산자를 이용하여 도큐먼트 특정 필드 수정
1.1 대치에 의한 수정
user_id = ObjectId("4c4b1476238d3b4dd5003981");
doc = db.users.findOne({_id: user_id}); // 1.도큐먼트 조회
doc['email'] = 'mongodb-user@mongodb.com'; // 2.조회한 도큐먼트에 대한 수정
db.users.update({_id: user_id}, doc); // 3.수정한 도큐먼트로 대치
- 여러 사용자가 동일한 도큐먼트를 업데이트하는 경우 마지막으로 쓰기 연산이 수행된 내용이 저장
1.2 연산자에 의한 수정
user_id = ObjectId("4c4b1476238d3b4dd5000001")
db.users.update({_id: user_id},
{$set: {email: 'mongodb-user2@mongodb.com'}} // $set 연산자를 이용하여 email 변경
)
- $set 연산자를 사용하여 필드를 주어진 값으로 설정
1.3 비교
- 대치 방식 장점
- 복잡한 모델링 시 연산자에 대한 최적의 조합을 계산하는 것보다 쉬움
- 연산자 방식 장점
- 수정할 도큐먼트를 가져오기 위한 조회가 필요 없음
- 업데이트를 지정할 도큐먼트 크기가 일반적으로 작음
- 원자적으로 업데이트 시 적합
2. 원자적 도큐먼트 프로세싱
- 다른 연산이 인터럽트하거나 인터리브 할 수 없는 업데이트
- 모든 업데이트는 원자적이지만 findAndModify는 도큐먼트 자동 반환
- findAndModify는 default로 업데이트 이전 도큐먼트 반환
- new: true 옵션을 추가해주면 업데이트 이후의 도큐먼트 반환
// 업데이트 이후 도큐먼트
newDoc = db.orders.findAndModify({
query: {
user_id: ObjectId("4c4b1476238d3b4dd5000001"),
state: 'CART'
},
update: {
$set: {
state: 'PRE-AUTHORIZE'
}
},
'new': true // 업데이트 이후의 도큐먼트 반환 옵션
})
// 업데이트 이전 도큐먼트
oldDoc = db.orders.findAndModify({
query: {
user_id: ObjectId("4c4b1476238d3b4dd5000001"),
total: 99000,
state: "PRE-AUTHORIZE"
},
update: {
'$set': {
state: "AUTHORIZING"
}
}
})
3. MongoDB 업데이트와 삭제
3.1 업데이트 타입과 옵션
- 타깃 방식과 대치 방식 업데이트 지원
- 도큐먼트가 모오하면 업데이트는 실패
// 도큐먼트 이름 변경
// 쿼리 셀렉터와 일치하는 첫 번째 도큐먼트만을 업데이트
db.products.update_one({},
{$set: {name: "Pitchfork"}, $addToSet: {tags: 'cheap'}})
// 다중 도큐먼트 업데이트
// 일치하는 도큐먼트 모두 업데이트를 위해 multi: true 매개변수 추가 필요
db.products.update({}, {$addToSet: {tags: 'cheap'}}, {multi: true})
- 업서트
- 도큐먼트가 없을 경우 새로 추가하고 이미 있다면 업데이트 처리
- 대치 방식의 업데이트에서는 수행 X
db.products.update({slug: 'hammer'},
{$addToSet: {tags: 'cheap'}}, {upsert: true})
3.2 업데이트 연산자
- 연산자
- $inc : 주어진 값에 따라 필드 값 증가
- $set : 필드를 주어진 값으로 설정
- $unsert : 전달받은 필드의 설정을 해제
- $rename : 필드의 이름을 주어진 값으로 변경
- $setOnInsert : upsert에서 삽입이 발생할 때만 필드를 설정
- $bit : 필드의 비트 단위 업데이트를 수행
- 배열 연산자
- $ : 쿼리 셀렉터에 의해 발견된 위치에서 하위 도큐먼트를 업데이트
- $push : 배열에 값을 추가
- $pushAll : 배열에 값 배열을 추가. 더 이상 사용되지 않고 대신 $each를 사용
- $addToSet : 배열에 값을 추가하지만 그것이 중복되면 아무것도 하지 않음
- $pop : 배열의 첫 번째 또는 마지막 항목을 제거
- $pull : 주어진 쿼리와 일치하는 배열에서 값을 제거
- $pullAll : 배열에서 여러 값을 제거
- 배열 연산자 수정자
- $each : 이 연산자를 여러 값에 적응하려면 $push 및 $addToSet과 함께 사용
- $slice : $push 및 $each와 함께 사용하여 업데이트된 배열을 특정 크기로 분할
- $sort : 분할하기 전에 $push, $each 및 $slice와 함께 배열의 하위 도큐먼트를 정렬하는 데 사용
- 독립 연산
- $isolated : 여러 도큐먼트 업데이트에 다른 연산이 끼어드는 것을 허용하지 않음
3.3 findAndModify 명령
- 수정 전 또는 이후의 도큐먼트 반환
- default : 수정 전 도큐먼트 반환
- new: true 옵션을 추가해주면 업데이트 이후의 도큐먼트 반환
- 삭제, 대체, 갱신이라는 세 가지 작업의 기능을 결함한 메서드로 사용자 오류가 발생하기 쉬움
- 3.2 버전에서 findAndModify을 수용한 3개의 컬렉션 메서드 추가
- findOneAndDelete
- findOneAndReplace
- findOneAndUpdate
- new 대신 returnNewDocument 필드 사용
doc = db.orders.findAndModify({
query: {
user_id: ObjectId("4c4b1476238d3b4dd5000001"),
},
update: {
$set: {
state: "AUTHORIZING"
}
}
})
3.4 삭제
// 모든 리뷰 삭제
db.reviews.remove({})
// 특정 사용자 리뷰 삭제
db.reviews.remove({user_id: ObjectId('4c4b1476238d3b4dd5000001')})
출처
- MongoDB in Action 2nd
- MongoDB 완벽 가이드