티스토리 뷰
다음을 포함한 데이터베이스에서의 기본적인 데이터 입출력을 다룬다.
- 컬렉션에 새 도큐먼트 추가하기
- 컬렉셔네서 도큐먼트 삭제하기
- 기존 도큐먼트 갱신하기
- 연산(operation)을 수행할 때 안전성과 속도 중 맞는 수준 선택하기
3.1 도큐먼트 삽입
삽입은 몽고DB에 데이터를 추가하는 기본 방법이다. 컬렉션의 insertOne 메서드를 사용한다.
db.movies.insertOne({"title": "STand by Me"})
3.1.1 insertMany
여러 도큐먼트를 컬렉션에 삽입하려면 insertMany로 도큐먼트 배열을 데이터베이스에 전달한다. 코드가 삽입된 각 도큐먼트에 대해 데이터베이스로 왕복하지 않고 도큐먼트를 대량 삽입(bulk insert)하므로 훨씬 효율적이다.
insertMany는 여러 도큐먼트를 단일 컬렉션에 삽입할 때 유용하다. 몽고DB의 현재 버전에서는 48메가바이트까지의 크기 제한을 두고 있다.
insertMany의 두번째 매개변수로 옵션 도큐먼트를 지정할 수 있다. 도큐먼트가 제공된 순서대로 삽입되도록 옵션 도큐먼트에 "orderId"키에 true를 지정한다. 순서가 지정되지 않았다면 정렬된 삽입이 기본값이다.
3.1.2 삽입 유효성 검사
유효하지 않은 데이터가 입력되지 않도록 _id필드와 용량(16메가바이트) 등의 최소한의 검사를 수행한다.
3.1.3 삽입
몽고DB 3.0 이전에서는 insert만 사용했으나 3.2의 경우 insertOne과 insertMany 등의 API를 지원한다. 이전 버전과의 호환성 때문에 insert를 지원하나 가급적 insertOne과 insertMany를 사용하자.
3.2 도큐먼트 삭제
데이터 삭제에는 deleteOne과 deleteMany를 제공한다. 두 메서드 모두 필터 도큐먼트를 첫 번째 매개변수로 사용한다.
db.movies.deleteOne({"_id":4})
컬렉션 내 여러 도큐먼트와 일치하는 필터를 지정할 수도 있는데 이때 deleteOne은 필터와 일치하는 첫 번째 도큐먼트를 삭제한다. 어떤 도큐먼트가 먼저 발견되는지는 도큐먼트가 삽입되는 순서, 갱신, 인덱스 지정등의 요인에 따라 달라진다.
몽고DB 3.0 이전 버전에는 도큐먼트를 삭제하는 데 remove를 주로 사용했다. remove는 이전 버전과의 호환성을 위해 지원되지만 deleteOne과 deleteMany를 사용하자.
3.2.1 drop
전체 컬렉션을 삭제하려면 다음과 같이 drop을 사용하는 편이 delete보다 빠르다.
db.movies.drop()
그리고 빈 컬렉션에 인덱스를 재생성한다.
이전에 백업된 데이터를 복원하는 방법 외에 delete 또는 drop 작업을 취소하거나 삭제된 도큐먼트를 복구한느 방법은 없다.
백업및 복원에 대한 내용은 23장에 다시 다룬다.
3.3 도큐먼트 갱신
updateOne, updateMany, replaceOne과 같은 갱신 메서드를 사용해 변경한다.
updateOne과 updateMany는 필터 도큐먼트를 첫 번째 매개변수로, 변경 사항을 설명하는 수정자 도큐먼트를 두 번째 매개변수로 사용한다.
replaceOne도 첫 번째 매개변수로 필터를 사용하지만 두 번째 매개변수는 필터와 일치하는 도큐먼트를 교체할 도큐먼트다.
갱신은 원자적으로 이뤄진다. 갱신 요청 두 개가 동시에 발생하면 서버에 먼저 도착한 요청이 적용된 후 다음 요청이 적용된다. 따라서 마지막 요청이 결국 최후의 승리자가 되므로 도큐먼트를 변질없이 안전하게 처리된다.
3.3.1 도큐먼트 치환
replaceOne은 도큐먼트를 새로운 것으로 완전히 치환한다. 이는 대대적인 스키마 마이그레이션에 유용하다.
즉 스키마 변경시에 유용하다.
3.3.2 갱신 연산자
일반적으로 도큐먼트의 특정 부분만 갱신하는 경우가 많다. 부분 갱신에는 원자적 갱신 연산자를 사용한다. 갱신 연산자는 키를 변경, 추가, 제거하고, 심지어 배열과 내장 도큐먼트를 조작하는 복잡한 갱신 연산을 지정하는 데 사용하는 특수키다.
$set 제한자 사용하기
$set은 필드 값을 설정한다. 필드가 존재하지 않으면 새 필드가 생성된다. 이 기능은 스키마를 갱신하거나 사용자 정의 키를 추가할 때 편리하다.
$set은 키의 데이터형도 변경할 수 있다. 기존 문자열을 배열로도 변경 가능하다.
db.users.updateOne({"name": "joe"}, {"$set": {"favorite book" : ["....", "blabla"]}})
$unset을 이용하여 키와 값을 모두 제거할 수도 있다.
db.uesrs.updateOne({"name": "joe"}, {"$unset: {"favorite book": 1}})
증가와 감소
$inc 연산자는 이미 존재하는 키의 값을 변경하거나 새 키를 생성하는 데 사용한다. 분석, 분위기, 투표 등과 같이 자주 변하는 수치 값을 갱신하는 데 매우 유용하다.
$inc는 $set과 비슷하지만 숫자를 증감하기 위해 설계 됐다. int, long, double, decimal 타입 값에만 사용할 수 있다. null, 불리언, 문자열로 나타낸 숫자와 같이 여러 언어에서 숫자로 자동 변환되는 데이터형의 값에는 사용할 수 없다.
배열 연산자
요소 추가하기
$push는 배열이 이미 존재하면 배열 끝에 요소를 추가하고, 존재 하지 않으면 새로운 배열을 생성한다.
$push에 $each 제한자를 사용하면 작업 한 번으로 값을 여러 개 추가할 수 있다.
또한, 배열을 특정 길이로 늘이려면 $slice를 $push와 결합해 사용한다. 배열이 특정 크기 이상으로 늘어나지 않게 하고 효과적으로 'topN' 목록을 만들 수 있다.
$slice나 $sort를 배열상에서 $push와 함께 쓰려면 반드시 $each도 포함해야 한다.
배열을 집합으로 사용하기
특정 값이 배열에 존재하지 않을 때 해당 값을 추가하면서, 배열을 집합처럼 처리하려면 쿼리 도큐먼트에 $ne를 사용한다.
$addToSet은 $ne가 작동하지 않을 때나 $addToSet을 사용하면 무슨 일이 일어났는지 더 잘 알수 있을 때 유용하다.
고유한 값을 여러 개 추가하려면 $addToSet과 $each를 결합해 사용한다. 이는 $ne와 $push조합으로는 할 수 없는 작업이다.
요소 제거
배열을 큐나 스택처럼 사용하려면 배열의 양쪽 끝에서 요소를 제거하는 $pop을 사용한다.
{"$pop": {"key": 1}} //배열의 마지막 부터 요소 제거
{"$pop": {"key": -1}} //배열의 처음 부터 요소 제거
$pull은 주어진 조건에 맞는 배열 요소를 제거하는데 사용한다. 도큐먼트에서 조건과 일치하는 요소를 모두 제거한다.
배열의 위치 기반 변경
배열 내 여러 값을 다루는 방법은 위치를 이용하거나 위치 연산자($)를 사용한다.
배열 필터를 이용한 갱신
몽고DB 3.6에서는 개별 배열 요소를 갱신하는 배열 필터인 arrayFilters를 도입해 특정 조건에 맞는 배열 요소를 갱신할 수 있다.
예를 들어 반대표가 5표 이상인 댓글을 숨기거나 할 수 있다.
arrayFilters: [{"elem.votes": {$lie: -5}}]
3.3.3 갱신 입력
갱신 입력은 특수한 형태를 갖는 갱신이다. 갱신 조건에 맞는 도큐먼트가 존재하지 않을 때는 쿼리 도큐먼트와 갱신 도큐먼트를 합쳐서 새로운 도큐먼트를 생성한다. 조건에 맞는 도큐먼트가 발견되면 일반적인 갱신을 수행한다.
갱신 입력을 사용하면 코드를 줄이고 경쟁 상태를 피할 수 있다. updateOne과 updateMany의 세번째 매개변수는 옵션 도큐먼트로, 갱신 입력을 지정한다.
db.analytics.updateOne({"url": "/blog"}, {"$inc": {"pageviews: 1}}, {"upsert": true})
도큐먼트가 생성될 때 필드가 설정돼야 할 때가 종종 있는데, 이후 갱신에서는 변경되지 않아야 한다. 이때 $setOnInsert를 사용한다. 이는 도큐먼트가 삽입될 때 필드값을 설정하는 데만 사용하는 연산자다.
저장 셸 보조자
save는 도큐먼트가 존재하지 않으면 도큐먼트를 삽입하고, 존재하면 도큐먼트를 갱신하게 하는 셸 함수다.
도큐먼트가 _id키를 포함하면 save는 갱신 입력을 실행하고, 포함하지 않으면 삽입을 실행한다.
var x = db.testcol.findOne()
x.num = 42
db.testcol.save(x)
3.3.4 다중 도큐먼트 갱신
updateMany는 스키마를 변경하거나 특정 사용자에게 새로운 정보를 추가할 때 쓰기 좋다.
예를 들어 특정 날짜에 생일을 맞이하는 모든 사용자에게 선물을 준다고 가정하면 updateMany를 통해 gift를 추가할 수 있다.
3.3.5 갱신한 도큐먼트 반환
일부 사례에서는 수정된 도큐먼트를 반환하는 것이 중요한데, 몽고DB의 이전 버전에서는 그럴 때 findAndModify를 사용했다.
그러나 이는 삭제, 대체, 갱신이라는 세 가지 작업의 기능을 결합한 복잡한 메서드이므로 사용자 오류가 발생하기 쉽다.
몽고DB 3.2에서는 findOneAndDelete, findOneAndReplace, findOneAndUpdate를 셸에 도입했다. updateOne 같은 메서드와의 큰 차이점은 사용자가 수정된 도큐먼트의 값을 원자적으로 얻을 수 있다는 점이다. 이는 한번의 연산으로 반환하고 갱신할 수 있어서 경쟁 상태를 피할 수 있다.
몽고DB 4.2는 갱신을 위한 집계 파이프라인을 수용하도록 findOneAndUpdate를 확장했다. 파이프라인은 $addFields(별칭 $set), $project(별칭 $unset), $replaceRoot(별칭 $replaceWith)로 구성될 수 있다.
findOneAndUpdate 메서드는 기본적으로 도큐먼트의 상태를 수정하기 전에 반환한다. 옵션 도큐먼트의 returnNewDocument 필드를 true로 설정하면 갱신된 도큐먼트를 반환한다.
findOneAndReplace는 동일한 매개변수를 사용하며, returnNewDocument의 값에 따라 교체 전이나 후에 필터와 일치하는 도큐먼트를 반환한다.
findOneAndDelete도 유사하지만 갱신 도큐먼트를 매개변수로 사용하지 않으며 다른 두 메서드의 옵션을 부분적으로 가진다. 삭제된 도큐먼트를 반환한다.
출처
'DB > MongoDB' 카테고리의 다른 글
[몽고DB 완벽 가이드 3판] 몽고 DB 기본 (0) | 2022.08.28 |
---|---|
[몽고DB 완벽 가이드 3판] 몽고 DB 소개 (0) | 2022.08.23 |
- Total
- Today
- Yesterday
- 뱅크샐러드 유전자
- springboot https
- MSSQL
- java
- multiple row update
- gradle
- 이펙티브자바
- vue.js
- update query
- update query mutiple row
- 슬랙봇
- update set multiple
- visual studio code
- Slack
- 그레이들
- 싱글턴
- 이것이 자바다
- 뱅셀 유전자
- update query multi row
- 뱅크샐러드
- update query set multiple
- 업데이트 쿼리
- update set multi
- effectivejava
- SpringBoot
- spring-boot-starter-data-redis
- 몽고DB 완벽가이드
- 슬랙 /
- 다중 업데이트
- 슬랙
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |