Database/Mongo

배열과 내장 document 를 다루는 방법 (Update)

Jeffrey Oh 2023. 3. 6. 22:49
반응형

샘플 데이터 삽입

db.students.insertMany([
    {_id: 1, grades: [85, 80, 80]},
    {_id: 2, grades: [88, 90, 92]},
    {_id: 3, grades: [85, 100, 90]},
])

포지셔닝 연산자

조건에 해당하는 배열 요소 수정

db.students.updateOne(
    { _id: 1, grades: 90 },
    {$set : {"grades.$" : 82}}
)

전체 요소를 10씩 증가

db.students.updateMany(
    {},
    {$inc : {"grades.$[]" : 10}}
)

document 를 배열로 가지는 document 추가

db.students.insertMany([
    {
        _id: 4,
        grades: [
            {grade: 80, mean: 75, std: 8},
            {grade: 85, mean: 90, std: 5},
            {grade: 85, mean: 85, std: 8}
        ]
    }
])

처음 만나는 document 중 _id 가 4이면서 grade 값이 85인 document 의 std 값을 6으로 수정

db.students.updateOne(
    { _id: 4, "grades.grade" : 85 },
    { $set: { "grades.$.std": 6 } }
)

_id 가 4이면서 grade 값이 85 보다 큰 document 들의 grade 를 100으로 수정

왜 grade 80 짜리도 100으로 수정되는지 이해가 안됨

db.students.updateOne(
    { _id: 4, grades : { $elemMatch: { grade: { $gte: 85 } } } },
    { $set: { "grades.$[].grade": 100 } }
)
db.students.insertMany([
    {
        _id: 5,
        grades: [
            {grade: 90, mean: 75, std: 8},
            {grade: 87, mean: 90, std: 5},
            {grade: 85, mean: 85, std: 8}
        ]
    }
])

element 를 직접 property 로 호출하여 arrayFilters 를 거는 방식

얘는 확실하게 조건에 맞는 것들만 수정이됨

db.students.updateOne(
    { _id: 5 },
    { $set: { "grades.$[element].grade": 100 } },
    { arrayFilters: [{"element.grade": { $gte: 87 }}] }
)
db.students.insertOne(
    {
        _id: 7,
        grades: [
            { type: "quiz", quetions: [ 10, 8, 5 ] },
            { type: "quiz", quetions: [ 8, 9, 6 ] },
            { type: "hw", quetions: [ 5, 4, 3 ] },
            { type: "exam", quetions: [ 25, 10, 23, 0 ] }
        ]
    }
)

property(identify) 값은 임의로 지정가능
score 로 지정하여 arrayFilters 에서 이용
quetions field 의 배열 요소들을 가리키는 임의 식별값 score 를 8보다 큰 값들을 2씩 증가

db.students.updateOne(
    { _id: 7 },
    { $inc: { "grades.$[].quetions.$[score]": 2} },
    { arrayFilters: [{ score: { $gte: 8 } }] }
)

배열의 값을 추가 및 삭제

예제 코드 삽입

db.shopping.insertMany([
    {
        _id: 1,
        cart: [ "bannana", "cheeze", "milk" ],
        coupons: [ "10%", "20%", "30%" ]
    },
    {
        _id: 2,
        cart: [],
        coupons: []
    }
])

addToSet 연산자는 값을 넣으려고 할 때 중복되지 않는 경우만 추가하는 연산자

db.shopping.updateOne(
    { _id: 1 },
    { $addToSet: { cart: "beer" } }
)

여러개를 한번에 추가하려고 할 때 배열을 이용하면 안되는 이유

db.shopping.updateOne(
    { _id: 1 },
    { $addToSet: { cart: [ "beer", "candy" ] } }
)

위의 쿼리를 실행하면 배열 자체가 값으로 들어간다

{
    _id: 1,
    cart: [ 'bannana', 'cheeze', 'milk', 'beer', [ 'beer', 'candy' ] ],
    coupons: [ '10%', '20%', '30%' ]
}

따라서 각각 넣기위해서는 each 연산자를 이용하면 된다

db.shopping.updateOne(
    { _id: 1 },
    { $addToSet: { cart: { $each : [ "beer", "candy" ] } } }
)

배열 요소를 삭제하기 위해서는 pull 연산자를 사용

db.shopping.updateOne(
    { _id: 1 },
    { $pull : { cart: "beer" } }
)

여러개를 삭제하려면 in 연산자 이용

db.shopping.updateOne(
    { _id: 1 },
    { $pull : { cart: { $in : [[ "beer", "candy" ], "milk" ] } } }
)

배열 사이즈가 큰 경우에 addToSetpull 연산자를 사용하면 시간복잡도가 커서 수행속도가 느리다


pop, push

pop 을 사용시 음수는 가장 첫번째를 제거하고 양수는 가장 끝의 요소를 제거한다

db.shopping.updateOne(
    { _id: 1 },
    { $pop: { cart: -1 } }
)

동시에 여러 필드 배열을 제거할 수 도 있다

db.shopping.updateOne(
    { _id: 1 },
    { $pop: { cart: 1, coupons: -1 } }
)

push 는 맨 끝에 요소가 추가된다

db.shopping.updateOne(
    { _id: 1 },
    { $push: { cart: "popcorn" } }
)
db.shopping.updateOne(
    { _id: 1 },
    { $push: { coupons: { $each : [ "25%", "35%" ] } } }
)

position 연산자를 이용하면 어느 위치에 추가할지 선택할 수 있다

db.shopping.updateMany(
    {},
    {
        $push: {
            coupons: {
                $each: [ "90%", "70%" ],
                $position: 0
            }
        }
    }
)

slice 연산자를 이용하면 배열의 크기를 제어할 수 있다

db.shopping.updateMany(
    {},
    {
        $push: {
            coupons: {
                $each: [ "15%", "20%" ],
                $position: 0,
                $slice: 5
            }
        }
    }
)

위 쿼리를 실행하면 _id 값이 1인 coupons 에서의 배열의 크기가 5가 넘으면서 position 값이 0이므로 맨 앞부터
값이 채워지기 때문에 맨 끝에 있던 요소 중 오버되는 요소는 자동으로 삭제된다


sort 배열을 정렬해주는 연산자

db.shopping.updateMany(
    {},
    {
        $push: {
            coupons: {
                $each: [ "90%", "99%" ],
                $position: -1,
                $sort: -1,
                $slice: 5
            }
        }
    }
)
반응형