❑ 공통 데이터 Insert
db.students.insertMany([
{_id: 1, grades: [85, 80, 80]},
{_id: 2, grades: [88, 90, 92]},
{_id: 3, grades: [85, 100, 90]}
])
❑ 배열의 값 변경하기 : $set
[참고] $ : Positioning Operator
1. Array.$ : 배열 내 조건과 일치하는 첫 번째 element에 적용
1.1. 배열 Element가 Value일 때 Update
AS-IS)
{
_id: 1,
grades: [85, 80, 80]
}
MQL)
db.students.updateOne(
{ _id: 1, grades: 80 },
{ $set: { "grades.$": 82 } }
)
- _id:1 이고, grades 배열에 값이 80인 첫 번째 element를 82로 변경
TO-BE)
{
_id: 1,
grades: [85, 82, 80]
}
- _id:1, grades:80 인 element는 두 개 가 있었지만 첫 번째 element에만 적용됨
1.2. 배열 Element가 내장 Document 일 때 Update
AS-IS)
{
_id: 1,
grades: [
{ grade: 80, mean: 75, std: 8 },
{ grade: 85, mean: 90, std: 5 },
{ grade: 85, mean: 85, std: 8 }
]
}
MQL)
db.students.updateOne(
{ _id: 1, "grades.grade": 85 },
{ $set: { "grades.$.std": 6 } }
)
- _id:1 이고, grades 배열의 내장 Document 중 grade 값이 85인 첫 번째 Document를 찾아 std field를 6으로 변경
TO-BE)
{
_id: 1,
grades: [
{ grade: 80, mean: 75, std: 8 },
{ grade: 85, mean: 90, std: 6 }, # grade: 85 인 첫 번째 내장 Document
{ grade: 85, mean: 85, std: 8 }
]
}
2. Array.$[] : 배열 내 조건과 일치하는 모든 element에 적용
2.1. 배열 Element가 Value일 때 Update
AS-IS)
{
_id: 1,
grades: [85, 80, 80]
}
{
_id: 2,
grades: [88, 90, 92]
}
MQL)
db.students.updateMany(
{},
{ $inc: { "grades.$[]": 3} }
)
- 모든 document의 grades 배열의 element를 3씩 증가(inc)시키겠다
TO-BE)
{
_id: 1,
grades: [88, 83, 83]
}
{
_id: 2,
grades: [91, 93, 95]
}
2.2. 배열 Element가 내장 Document 일 때 전체 Document Update
AS-IS)
{
_id: 1,
grades: [
{ grade: 80, mean: 75, std: 8 },
{ grade: 85, mean: 90, std: 5 },
{ grade: 85, mean: 85, std: 8 }
]
}
MQL)
db.students.updateOne(
{ _id: 1, grades: {$elemMatch: {grade: {$gte: 85}}} },
{ $set: { "grades.$[].grade": 100 } }
)
- _id:1 이고, grades 배열의 내장 Document 중 grade 값이 85와 같거나 큰 Document가 있다면, 배열의 모든($[]) Document의 grade를 100으로 변경
- $gte : greater than or eqaul (크거나 같다)
TO-BE)
{
_id: 1,
grades: [
{ grade: 100, mean: 75, std: 8 },
{ grade: 100, mean: 90, std: 5 }, # as-is의 grade 값이 85 이므로 $gte: 85를 만족
{ grade: 100, mean: 85, std: 8 } # as-is의 grade 값이 85 이므로 $gte: 85를 만족
]
}
2.3. 배열 Element가 내장 Document 일 때 특정 Document Update - arrayFilters 사용
AS-IS)
{
_id: 1,
grades: [
{ grade: 80, mean: 75, std: 8 },
{ grade: 85, mean: 90, std: 5 },
{ grade: 85, mean: 85, std: 8 }
]
}
MQL)
db.students.updateMany(
{ _id: 1 },
{ $set: { "grades.$[element].grade": 100 } },
{ arrayFilters: [{"element.grade": {$gte: 83} }] }
)
- $[element]에서 element를 identifier라고 함. 일종의 변수로 지정한 것이고, arrayFilters에서 사용하게 됨. element라는 이름 대신 다른 것을 사용해도 상관없음
- _id:1 이고, arrayFilters에 따라 grades의 내장 Document를 지칭하는 element의 grade field가 83보다 크거나 같은 값을 찾아 100으로 변경한다
TO-BE)
{
_id: 1,
grades: [
{ grade: 80, mean: 75, std: 8 },
{ grade: 100, mean: 90, std: 5 }, # as-is의 grade 값이 85 이므로 $gte: 83를 만족
{ grade: 100, mean: 85, std: 8 } # as-is의 grade 값이 85 이므로 $gte: 83를 만족
]
}
❑ 배열에 element 추가하기 : $addToSet, $Push
0. $addToSet과 $Push의 차이
$addToSet
- $addToSet 연산자는 배열에 값을 추가할 때, 해당 값이 배열에 이미 존재하는지 여부를 확인하고 중복을 허용하지 않는다.
- 만약 배열에 추가하려는 값이 이미 존재한다면, 추가를 하지 않고 기존 값들을 그대로 유지.
- 배열에 중복된 값을 추가하지 않으며, 값의 유일성을 보장한다.
- addToSet은 배열 전체를 탐색하므로 시간 복잡도가 높다. 배열의 element가 많을 경우 부하가 클 수 있다.
$push
- $push 연산자는 배열에 값을 추가할 때, 중복 여부를 확인하지 않고 항상 값을 배열에 추가한다.
- 새로운 값이 배열에 추가되면 중복되어도 무조건 추가됨.
- push는 배열의 마지막 index만 보기 때문에 시간 복잡도가 낮다. 따라서 부하가 작다.
1. $addToSet
AS-IS 데이터
{
_id: 1,
cart: ['banana', 'cheeze', 'milk']
}
1.1. 값 타입 element 한 개 추가
MQL)
db.shopping.updateOne(
{ _id: 1 },
{ $addToSet: {cart: 'beer'} }
)
- cart 배열에 ‘beer’ 추가
TOBE)
{
_id: 1,
cart: ['banana', 'cheeze', 'milk', 'beer']
}
1.2. 배열 타입 element 한 개 추가
MQL)
db.shopping.updateOne(
{ _id: 1 },
{ $addToSet: {cart: ['beer', 'candy']} }
)
TOBE)
{
_id: 1,
cart: ['banana', 'cheeze', 'milk', ['beer', 'candy']]
}
1.3. 값 타입 element 여러 개 추가 - $each 사용
MQL)
db.shopping.updateOne(
{ _id: 1 },
{ $addToSet: { cart: { $each: ['beer', 'candy'] }} }
)
- $each 오퍼레이터를 사용한다
TOBE)
{
_id: 1,
cart: ['banana', 'cheeze', 'milk', 'beer', 'candy']
}
- beer, candy가 값 타입으로 들어감
2. $push
AS-IS 데이터
{
_id: 1,
cart: ['banana', 'cheeze', 'milk']
}
1.1. element 한 개를 마지막에 추가
MQL)
db.shopping.updateOne(
{ _id: 1 },
{ $push: {cart: 'beer'} }
)
TOBE)
{
_id: 1,
cart: ['banana', 'cheeze', 'milk', 'beer']
}
1.2. element 여러 개 마지막에 추가 - $each 사용
MQL)
db.shopping.updateOne(
{ _id: 1 },
{ $push: {cart: {$each : ['beer', 'candy']}} }
)
TOBE)
{
_id: 1,
cart: ['banana', 'cheeze', 'milk', 'beer', 'candy']
}
1.3. element 여러 개를 특정 index에 추가 - $position 사용
MQL)
db.shopping.updateOne(
{}, # 모든 document에 적용
{
$push: {
cart: {
$each : ['beer', 'candy'],
$position: 0 # index = 0 번째에 element 추가
}
}
}
)
- position: -1은 가장 끝이다
TOBE)
{
_id: 1,
cart: ['beer', 'candy', 'banana', 'cheeze', 'milk']
}
- beer, candy가 0번째 index에 추가됨
1.4. 배열의 크기를 유지하며 element를 추가 - $slice 사용
MQL)
db.shopping.updateOne(
{}, # 모든 document에 적용
{
$push: {
cart: {
$each: ['beer', 'candy'],
$position: 0,
$slice: 4 # 배열의 크기를 4개로 유지
}
}
}
)
TOBE)
{
_id: 1,
cart: ['beer', 'candy', 'banana', 'cheeze']
}
- beer, candy가 0번째 index에 추가됨
- 배열의 크기를 4개로 유지해야 하므로 가장 마지막 element였던 milk가 제거됨
❑ 배열에서 element 제거하기 : $pull, $pop
0. $pull과 $pop의 차이
- $pull은 $addToSet과 같이 배열 전체를 탐색하므로 시간 복잡도가 높고, 배열의 element가 많을 경우 부하가 높을 수 있다.
- $pop은 $push와 같이 index의 가장 마지막만 보기 때문에 시간 복잡도나 낮다.
1. $pull
AS-IS 데이터
{
_id: 1,
cart: ['banana', 'cheeze', 'milk', ['beer', 'candy']]
}
1.1. element 한 개 제거
MQL)
db.shopping.updateOne(
{ _id: 1 },
{ $pull: {cart: 'banana'} }
)
TOBE)
{
_id: 1,
cart: ['cheeze', 'milk', ['beer', 'candy']]
}
1.2. element 여러 개 제거 - $in 사용
MQL)
db.shopping.updateOne(
{ _id: 1 },
{ $pull: {cart: {$in: [['beer', 'candy'], 'banana'] }} }
}
TOBE)
{
_id: 1,
cart: ['cheeze', 'milk']
}
2. $pop
AS-IS 데이터
{
_id: 1,
cart: ['banana', 'cheeze', 'milk'],
coupon: ['10%', '20%', '30%']
}
2.1. 한 개의 배열에서 element 삭제
MQL)
db.shopping.updateOne(
{ _id: 1 },
{ $pop: {cart: -1} }
}
- -1 : 배열의 첫 번째 element 삭제
- cart 배열의 첫 번째 element를 삭제한다
TOBE)
{
_id: 1,
cart: ['cheeze', 'milk'], # 'banana' 삭제
coupon: ['10%', '20%', '30%']
}
2.2. 두 개의 배열에서 element 삭제
MQL)
db.shopping.updateOne(
{ _id: 1 },
{ $pop: {cart: -1, coupon: 1} }
}
- -1 : 배열의 첫 번째 element 삭제
- 1: 배열의 마지막 element 삭제
- cart 배열의 첫 번째, coupon 배열의 마지막 element를 삭제한다
TOBE)
{
_id: 1,
cart: ['cheeze', 'milk'], # 'banana' 삭제
coupon: ['10%', '20%'] # '30%' 삭제
}
-1 : 배열의 첫 번째 element 삭제
1: 배열의 마지막 element 삭제
'Back-End > MongoDB' 카테고리의 다른 글
[MongoDB] MQL 기초 4 - 배열과 내장 Document를 다루는 방법 1 (Read) (0) | 2024.05.31 |
---|---|
[MongoDB] MQL 기초 3 - 유용한 CRUD 쿼리 함수 (0) | 2024.05.31 |
[MongoDB] MQL 기초 2 - 기본 CRUD (0) | 2024.05.31 |
[MongoDB] MQL 기초 1 - Query Filter와 Operator (0) | 2024.05.31 |
[MongoDB] SQL vs MQL 비교 문서 (0) | 2024.05.31 |