[NoSQL] MongoDB CRUD 학습

Yalstrax·2021년 7월 30일
4

Back End

목록 보기
7/22
post-thumbnail

MongoDB CRUD

CREATE

모든 MongoDB 도큐먼트는 모든 도큐먼트가 _id 필드를 기본값으로 반드시 가지고 있어야 한다는 공통점이 있습니다.

_id 필드의 값은 각 도큐먼트를 구별하는 역할을 합니다.

도큐먼트 내 필드와 값이 똑같다 할지라도, _id 값이 다르면 서로 다른 도큐먼트로 간주합니다.

반면에, 도큐먼트 내 필드와 값이 다르다고 하더라도, _id값이 같다고 하면 서로 같은 도큐먼트로 여겨 에러를 발생시킵니다.

따라서 각 도큐먼트는 고유한 _id 값을 가지고 있어야 합니다. 새로운 도큐먼트를 추가할 때, _id 값에 임의적으로 고유한 값을 생성해서 사용할 수도 있지만 보통은 ObjectId 타입(12byte, 24char)의 값으로 사용합니다.

또한 도큐먼트를 추가할 때, _id 필드와 값을 특정하지 않았다면, 자동적으로 _id 필드가 생성되고 값에 ObjectId 타입이 할당됩니다.

MongoDB에서 샘플로 제공하는 데이터를 보면 고유한 _id가 ObjectId 타입으로 정의된 것을 확인할 수 있습니다.

데이터를 삽입하기 위해, db.컬렉션이름.insert() 명령어를 사용하여 삽입할 수 있습니다.

() 안에는 JSON 형식으로 객체를 필드 : 값 쌍으로 넣어줍니다.

고유한 아이디 _id를 설정하지 않으면 자동으로 ObjectId로 생성되어 삽입됩니다.

컬렉션에 이미 존재하는 값을 삽입했고, .find()로 컬렉션에 해당하는 데이터가 존재하는지 확인할 수 있습니다.

고유한 아이디 필드를 제외하고 삽입하여 아이디를 제외한 다른 필드는 모두 같지만, 고유 아이디가 달라 삽입이 완료되었습니다.

같은 아이디로 할당하고 삽입하게되면 duplicate key error를 확인할 수 있습니다.

.insert()를 사용하면, 주어진 도큐먼트 배열의 인덱스 순서로 작업이 실행됩니다. 만약, duplicate key 에러가 나오는 순간, 작업은 중단 됩니다.

이런 문제를 ordered옵션을 추가하는 것으로 삽입 순서를 바꿀 수 있습니다.

추가적으로, MongoDB는 사용자로 하여금 쉽게 새로운 컬렉션이나 데이터베이스를 생성하길 원합니다.

그래서 만약 사용자가 존재하지 않는 컬렉션에 도큐먼트를 만드는 경우, 그와 동시에 컬렉션이 만들어지게 됩니다.

db.abcd.insert({...})

만약, abcd라는 컬렉션이 존재하지 않는데 위와 같이 명령어를 입력하면 abcd라는 컬렉션이 만들어짐과 동시에 도큐먼트를 삽입합니다.

READ

데이터베이스가 어떤 컬렉션을 갖고있는지 보기를 원한다면 show명령어를 사용할 수 있습니다.

show collection 명령어는 데이터베이스 안의 컬렉션 리스트를 확인할 수 있습니다.

어떤 컬렉션의 데이터에서 원하는 필드와 값을 가진 도큐먼트를 조회하고자 한다면, .find()로 수행할 수 있습니다.

MongoDB가 제공하는 샘플 데이터로 실습해보았습니다.

db.zips.find({"state" : "NY", "city" : "ALBANY"})

위 명령어는

zips라는 컬렉션에서 필드 : 값state : NY 인 것과, city : ALBANY인 도큐먼트를 조회한다는 명령어입니다.

위처럼 원하는 필드와 값을 조회할 수 있습니다.

db.zips.find() 이렇게 아무 쿼리도 넣지않으면, zips 컬렉션의 모든 데이터를 조회할 수 있습니다.

db.zips.find().count() 명령어는 zips 컬렉션에 존재하는 모든 데이터의 갯수를 조회하는 명령어입니다.

db.zips.findOne() 명령어는 zips 컬렉션에 존재하는 모든 데이터 중 무작위로 데이터 1개를 가져오는 명령어입니다.

findOne()의 괄호 안에 원하는 쿼리문을 넣으면 원하는 쿼리에 맞는 데이터를 1개 가져오게 됩니다.

UPDATE

mongo shell에서 도큐먼트를 업데이트 하기 위한 방법에는 updateOne, updateMany 2가지가 있습니다.

  • updateOne

    • 주어진 기준에 맞는 다수의 도큐먼트 중 첫번째 도큐먼트 하나만 업데이트
  • updateMany

    • 쿼리문과 일치하는 모든 도큐먼트 업데이트

미국의 우편번호 관련 데이터를 가지고 있는 zips라는 컬렉션에서 데이터를 가지고 왔습니다.

그리고 살펴보니 이 데이터에는 단순히 우편번호만 기재 되어 있는 것이 아니라, 우편 번호가 속한 도시이름, 주 이름 등이 기재되어 있고, 그 중에서도 pop이라는 필드에 해당 지역의 인구수를 기록해두었습니다.

그러나 이 데이터들은 몇 년 전의 데이터 입니다.

다시 말하면 기록되어 있는 인구수와 현재의 인구수는 일치하지 않을 수도 있습니다.

그래서 이 컬렉션의 대부분의 도시들 인구 수가 최소 10명정도 증가 했다고 가정한다면, 이때는 다수의 데이터를 업데이트 해야하기 때문에 updateMany 명령어가 적합합니다.

지역 인구 수를 업데이트 하기 위해서는 우선 updateMany 명령어를 사용합니다.

그리고 이 명령어의 첫번째 인자는 어떤 도큐먼트를 업데이트 할지 결정하는 쿼리문이 작성됩니다.

우리는 {“city”: “ALPINE”} 이라는 조건의 지역 인구수 데이터를 업데이트 할 것이기 때문에, 첫번째 인자에 {“city”: “ALPINE”} 쿼리문을 작성하였습니다.

그리고 두번째 인자는 발생할 업데이트 내용을 특정합니다.

{"$inc" : {"pop" :10}}는 업데이트하려는 필드와 증가하는 값을 설정하는 것으로, 필드의 값을 업데이트할 수 있습니다.

$inc는 MQL(MongoDB Query Language)의 업데이트 연산자입니다.

작업에 대한 응답을 살펴보면, matchedCountmodifiedCount로 나뉘어집니다.

해당 부분은 명령어에 들어가는 쿼리문 2개에 대한 응답입니다.

matchedCount는 첫번째 인자로 들어간 조건을 충족하는 도큐먼트의 수를 의미합니다.

여기서는 우리가 앞서 찾았던 도큐먼트의 수와 같이 9가 출력되었습니다.

그리고 modifiedCount는 두 번째 인자로 들어간 업데이트 연산자 $inc로 인해 수정된 도큐먼트의 수를 의미합니다.

$set 연산자를 사용하면 주어진 필드에 지정된 값을 업데이트합니다. 기존 값에 특정한 값을 증가하거나, 감소하는게 아니라 아예 지정한 값으로 재할당할 수 있습니다.

$push 연산자는 배열로 이루어진 필드의 값에 요소를 추가하기 위한 연산자입니다.

db.grades.updateOne({"student_id":250,"class_id":339},{"$push":{"scores":{"type":"extra credit","score":100}}})

위 연산자는 grades라는 컬렉션에 student_id가 250, class_id가 339인 도큐먼트를 업데이트합니다.

업데이트 내용은 score이라는 필드의 값이 배열로 이루어져 있는데, 이 배열에 새로운 typescore를 추가하는 것입니다. 위와 같이 작성하는 것으로 업데이트할 수 있습니다.

DELETE

  • deleteOne

    • 주어진 기준에 맞는 다수의 도큐먼트 중 첫번째 도큐먼트 하나를 삭제
  • deleteMany

    • 쿼리문과 일치하는 모든 도큐먼트 삭제

mongo shell을 사용하여 도큐먼트 및 컬렉션을 삭제하려고 한다면, deleteOne( )deleteMany( )를 사용할 수 있습니다.

기본적으로 앞서 배웠던 updateOne( )updateMany( )와 작동방식은 비슷합니다.

deleteOne( )을 사용하는 경우, _id 값으로 쿼리해 온 도큐먼트를 삭제하는 것이 좋은 접근법입니다. 우리가 만약 _id 값으로 쿼리를 하지 않는다면, 검색 쿼리문에 다양한 도큐먼트가 적합할 수 있기 때문입니다.

기준을 충족하는 도큐먼트가 많을 경우에는 deleteMany를 사용하여 다수의 도큐먼트를 삭제할 수도 있습니다.

컬렉션을 삭제하기 위해서는 drop이라는 명령어를 사용해야 합니다.

drop은 가져오기(importing)을 할 때에도 기존의 컬렉션과 가져오는 데이터 사이의 duplicate key 에러를 방지하기 위해서 사용하기도 했었습니다.

db.컬렉션이름.drop()으로 삭제할 수 있습니다.

profile
즐겁다면 그것만으로 만만세!

0개의 댓글