몽고 DB 배열
프로젝트를 하던 중 배열을 몽고DB의 배열로된 필드를 본격적으로 다뤄야 할 일이 생겼다. 이에 앞서 몽고 DB에서 배열을 다루는 다양한 방법을 정리한다.
몽고 DB는 JSON(저장은 BSON) 형식으로 다룰 수 있기 때문에 배열과 관련된 연산을 지원한다. 이번에 몽고DB의 배열과 관련된 연산을 정리한다.
예시와 함께 보기 위해 우선 아래 명령어를 입력하여 도큐먼트를 생성한다.
db .employee .insertOne ({
name :"departments"
})
배열 쿼리 연산자
$push
$push는 배열이 이미 존재하면 배열의 끝에 요소를 추가한다. 다른 연산들이 그렇듯 push 또한 존재하지 않으면 새로운 배열을 생성한다. 추후 설명할 $each를 사용하면 여러값을 필드에 삽입할 수 있지만, 그렇지 않을 경우 하나의 값만 삽입 가능하다.
db .employee .updateOne ({name :"departments"}, {$push :{department :"IT"}})
IT를 삽입하였다.
{ "_id" : ObjectId("644ea0f0f3516b617492ea1a"), "name" : "departments", "department" : [ "IT" ] }
두 번 사용하면?
{ "_id" : ObjectId("644ea0f0f3516b617492ea1a"), "name" : "departments", "department" : [ "IT", "IT" ] }
department 필드의 배열에 IT가 두 번 들어간 것을 확인 할 수 있다.
$position을 사용하면 특정 위치에 삽입을 할 수 있다. $each와 함께 사용한다. 이에 대한 예시는 아래 $each에서 기술한다.
$addToSet
배열에 값이 없을 때만 값을 추가한다.
db .employee .updateOne ({name :"departments"}, {$addToSet :{department :"Accounting"}})
{ "_id" : ObjectId("644ea0f0f3516b617492ea1a"), "name" : "departments", "department" : [ "IT", "IT", "Accounting" ] }
두 번 사용하면?
{ "_id" : ObjectId("644ea0f0f3516b617492ea1a"), "name" : "departments", "department" : [ "IT", "IT", "Accounting" ] }
새로운 값이 추가되지 않음을 확인할 수 있다.
$pop
배열의 첫 번째나 마지막 값을 제거한다. 큐나 스택에서 처음이나 마지막 요소만 뺄 수 있는 것을 생각하면 되겠다.
1은 마지막 요소, –1은 첫 요소를 삭제한다.
db .employee .updateOne ({name :"departments"}, {$pop :{department :1 }});
{ "_id" : ObjectId("644ea0f0f3516b617492ea1a"), "name" : "departments", "department" : [ "IT", "IT" ] }
$pull
배열에서 값이 일치하는 요소를 제거한다.
db .employee .updateOne ({name :"departments"}, {$pull :{department :"IT"}});
{ "_id" : ObjectId("644ea0f0f3516b617492ea1a"), "name" : "departments", "department" : [ ] }
$pullAll
배열에서 값이 일치하는 모든 요소를 제거한다.
$each
$push나 $addToSet 메소드들과 함께 사용하여 배열에 여러 값을 추가할 때 사용한다.
db .employee .updateOne ({name :"departments"}, {$push :{department :{$each :["IT", "CS", "HR"]}}})
{ "_id" : ObjectId("644ea0f0f3516b617492ea1a"), "name" : "departments", "department" : [ "IT", "CS", "HR" ] }
앞서 $push에서 설명한 $position 사용법은 아래와 같다.
db .employee .updateOne ({name :"departments"}, {$push :{department :{$each :["using position"], $position :1 }}})
{ "_id" : ObjectId("644ea0f0f3516b617492ea1a"), "name" : "departments", "department" : [ "No IT", "using position", "CS", "HR" ] }
$elemMatch
배열에서 일치하는 요소를 선택한다.
이를 확인하기 위해 아래와 같이 작성한다.
db .employee .insertOne ({
name :"depart2",
departments :[
{name :"HR"},
{name :"IT"}
]
})
{ "_id" : ObjectId("644ea836f3516b617492ea1c"), "name" : "depart2", "departments" : [ { "name" : "HR" }, { "name" : "IT" } ] } //임베디드 서브어레이의 형태이다. 객체 배열이라는 의미.
db .employee .find ({departments :{ $elemMatch :{name :"IT"}}})
여기서 eleMatch를 사용하면 해당하는 값을 얻을 수 있다. 즉 배열 내부의 각 요소가 입력값과 일치하는지 여부를 확인한다.
{ "_id" : ObjectId("644ea836f3516b617492ea1c"), "name" : "depart2", "departments" : [ { "name" : "HR" }, { "name" : "IT" } ] }
객체 배열내의 값이 아니라 그저 배열 내의 값중 입력값과 일치하는 것을 찾으려면 그저 아래와 같이 사용하면 된다.
db .collection .find ({ department :"IT" })
{ "_id" : ObjectId("6447f2d5b1e44249bd4e6150"), "name" : "minjeong", "age" : 21, "department" : "IT" }
{ "_id" : ObjectId("644ea0f0f3516b617492ea1a"), "name" : "departments", "department" : [ "IT", "CS", "HR" ] }
즉 값이 배열 내에 있어도 정상적으로 출력해준다.
$slice
배열의 일부분을 선택한다. 파이썬에서 지원하는 슬라이스와 유사하다.
따라서 –1을 마지막 요소를 의미, -2는 마지막에서 2번째를 의미 한다.
$sort
배열을 정렬한다.
+ dot notation
.을 사용하면 배열의 n번쨰 요소를 선택할 수 있다. 이를테면 0번째 요소 값을 바꾸려면?
db .employee .updateOne ({name :"departments"}, {$set :{"department.0":"No IT"}})
{ "_id" : ObjectId("644ea0f0f3516b617492ea1a"), "name" : "departments", "department" : [ "No IT", "CS", "HR" ] }
결과를 보다시피 IT가 No IT로 바뀌었다.
객체 배열도 바꿀 수 있을까?
db .employee .updateOne ({name :"depart2"}, {$set :{"departments.1": { name :"new IT", and :"HEllO world" }}})
1번 인덱스의 배열 요소에 name과 and를 키로 하는 필드로 하는 객체로 변경한다.
{ "_id" : ObjectId("644ea836f3516b617492ea1c"), "name" : "depart2", "departments" : [ { "name" : "HR" }, { "name" : "new IT", "and" : "HEllO world" } ] }
보다시피 정상적으로 변경되었음을 확인할 수 있다.
dot notation을 활용하면 각 필드 내부의 값에 쉽게 접근할 수 있다. 마치 JS의 객체와 유사하다고 볼 수 있다.
마지막으로 이를 이용해 위의 도큐먼트의 HELLO world BYE로 바꾸어보자.
db .employee .updateOne ({name :"depart2"}, {$set :{"departments.1.and":"Bye Bye"}})
{ "_id" : ObjectId("644ea836f3516b617492ea1c"), "name" : "depart2", "departments" : [ { "name" : "HR" }, { "name" : "new IT", "and" : "Bye Bye" } ] }
+ 이러한 작업은 positional operator를 사용하면 더욱 쉽다고한다. $를 사용하는데, 이는 동적으로 위치를 정해주는 역할을 한다. 쿼리 도큐먼트에 일치하는 첫 번째 위치(인덱스값)을 자동으로 할당한다.
즉 이런 예시가 가능하다.
db .employee .updateOne (
{"departments.and":"Bye Bye" },
{ "$set": { "departments.$.and":"hey" } }
)
보면 쿼리 도큐먼트는 departments.and이다. 즉 departments내의 and값이 Bye Bye인 필드의 위치를 $이 담는다.
따라서 $set과 위에서 배열에 숫자로 접근하는 방식을 통해 Bye Bye값을 hey로 바꾼 것이다.
{ "_id" : ObjectId("644ea836f3516b617492ea1c"), "name" : "depart2", "departments" : [ { "name" : "HR" }, { "name" : "new IT", "and" : "hey" } ] }
$ 사용 몽고DB 공식 문서:
https://www.mongodb.com/docs/manual/reference/operator/update/positional/
'컴퓨터 > NoSQL 데이터베이스' 카테고리의 다른 글
[DB] 몽고 DB의 CRUD(생성, 읽기, 수정, 삭제) 작업/각종 쿼리 연산 (0) | 2023.04.29 |
---|---|
[DB] 몽고DB에 대해서 알아보자 (0) | 2023.04.29 |
댓글