programing

MongoDB-문서 배열의 객체 업데이트 (중복 업데이트)

new-time 2020. 5. 14. 22:36
반응형

MongoDB-문서 배열의 객체 업데이트 (중복 업데이트)


다음과 같은 컬렉션이 있다고 가정 해 보겠습니다.

{
    "_id" : ObjectId("4faaba123412d654fe83hg876"),
    "user_id" : 123456,
    "total" : 100,
    "items" : [
            {
                    "item_name" : "my_item_one",
                    "price" : 20
            },
            {
                    "item_name" : "my_item_two",
                    "price" : 50
            },
            {
                    "item_name" : "my_item_three",
                    "price" : 30
            }
    ]
}

1- "item_name": "my_item_two"의 가격을 높이고 싶지

않은 경우

"items"배열에 추가해야합니다.2-두 필드를 동시에 업데이트하려면 어떻게해야합니까? 예를 들어, "my_item_three"의 가격을 높이고 동시에 "total"(동일한 값)을 늘리십시오.MongoDB 쪽에서이 작업을 선호합니다. 그렇지 않으면 클라이언트 쪽 (Python)에 문서를로드하고 업데이트 된 문서를 구성하고 MongoDB의 기존 문서로 바꿔야합니다.

업데이트

 

객체가 존재

하는 경우 이것이 시도하고 잘 작동합니다 .

db.test_invoice.update({user_id : 123456 , "items.item_name":"my_item_one"} , {$inc: {"items.$.price": 10}})

그러나 키가 존재하지 않으면 아무것도하지 않습니다. 또한 중첩 된 개체 만 업데이트합니다. 이 명령을 사용하여 "전체"필드도 업데이트 할 수있는 방법이 없습니다.


1 번 문제는 두 부분으로 나누겠습니다. 먼저 "items.item_name"이 "my_item_two"인 문서를 증가시킵니다. 이를 위해서는 위치 "$"연산자를 사용해야합니다. 다음과 같은 것 :

 db.bar.update( {user_id : 123456 , "items.item_name" : "my_item_two" } , 
                {$inc : {"items.$.price" : 1} } , 
                false , 
                true);

이는 배열에서 첫 번째로 일치하는 하위 문서 만 증가시킵니다 (따라서 "item_name"이 "my_item_two"인 배열에 다른 문서가있는 경우에는 증가하지 않습니다). 그러나 이것은 당신이 원하는 것일 수 있습니다.두 번째 부분은 더 까다 롭습니다. 다음과 같이 "my_item_two"없이 새 항목을 배열로 푸시 할 수 있습니다.

 db.bar.update( {user_id : 123456, "items.item_name" : {$ne : "my_item_two" }} , 
                {$addToSet : {"items" : {'item_name' : "my_item_two" , 'price' : 1 }} } ,
                false , 
                true);

2 번 문제는 답이 더 쉽습니다. "my_item_three"가 포함 된 문서에서 item_three의 총 가격과 가격을 높이려면 여러 필드에서 동시에 $ inc 연산자를 사용할 수 있습니다. 다음과 같은 것 :

db.bar.update( {"items.item_name" : {$ne : "my_item_three" }} ,
               {$inc : {total : 1 , "items.$.price" : 1}} ,
               false ,
               true);

단일 쿼리에서는이를 수행 할 방법이 없습니다. 첫 번째 쿼리에서 문서를 검색해야합니다.문서가 존재하는 경우 :

db.bar.update( {user_id : 123456 , "items.item_name" : "my_item_two" } , 
                {$inc : {"items.$.price" : 1} } , 
                false , 
                true);

그밖에

db.bar.update( {user_id : 123456 } , 
                {$addToSet : {"items" : {'item_name' : "my_item_two" , 'price' : 1 }} } ,
                false , 
                true);

조건을 추가 할 필요가 없습니다

{$ne : "my_item_two" }

.또한 다중 스레드 환경에서는 한 번에 하나의 스레드 만 두 번째 (문서를 찾을 수없는 경우 삽입 케이스)를 실행할 수 있도록주의해야합니다. 그렇지 않으면 중복 된 삽입 문서가 삽입됩니다.참고 URL :

https://stackoverflow.com/questions/10522347/mongodb-update-objects-in-a-documents-array-nested-updating

반응형