[mongodb] 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" }.

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


답변

우리가 사용할 수있는 $set객체가 값을 갱신 신청 안에 중첩 된 배열을 업데이트 연산자

db.getCollection('geolocations').update( 
   {
       "_id" : ObjectId("5bd3013ac714ea4959f80115"), 
       "geolocation.country" : "United States of America"
   }, 
   { $set: 
       {
           "geolocation.$.country" : "USA"
       } 
    }, 
   false,
   true
);


답변