[mongodb] 새로운 객체가 기존 객체와 오버레이 / 병합되도록 MongoDB에서 객체를 부분적으로 업데이트하는 방법

이 문서가 MongoDB에 저장된 경우

{
   _id : ...,
   some_key: { 
        param1 : "val1",
        param2 : "val2",
        param3 : "val3"
   }
}

새로운 정보를 가진 객체 param2param3외부 세계에서 저장해야

var new_info = {
    param2 : "val2_new",
    param3 : "val3_new"
};

param1이 제거되지 않도록 객체의 기존 상태 위에 새 필드를 병합 / 오버레이하고 싶습니다

이렇게

db.collection.update(  { _id:...} , { $set: { some_key : new_info  } } 

MongoDB가 요청 한대로 정확하게 작동하게하고 some_key를 해당 값으로 설정합니다. 오래된 것을 대체합니다.

{
   _id : ...,
   some_key: { 
      param2 : "val2_new",
      param3 : "val3_new"
   }
}

MongoDB가 새 필드 만 명시 적으로 업데이트하지 않는 방법은 무엇입니까? 이것을 얻으려면 :

{
   _id : ...,
   some_key: { 
        param1 : "val1",
        param2 : "val2_new",
        param3 : "val3_new"
   }
}

Java 클라이언트를 사용하고 있지만 모든 예를 들어 주시면 감사하겠습니다.



답변

질문을 올바르게 이해하면 다른 문서의 내용으로 문서를 업데이트하고 아직 존재하지 않는 필드 만 업데이트하고 이미 설정된 필드 (다른 값이더라도)를 완전히 무시하려고합니다.

단일 명령으로는 그렇게 할 수 없습니다.

먼저 문서를 쿼리하고 원하는 것을 $set파악한 다음 업데이트해야합니다 (이전 값을 일치하는 필터로 사용하여 사이에 동시 업데이트를받지 않도록해야합니다).


귀하의 질문에 대한 또 다른 독서는 당신이 만족 $set하지만 모든 필드를 명시 적으로 설정하고 싶지 않다는 것입니다. 그러면 데이터를 어떻게 전달 하시겠습니까?

다음을 수행 할 수 있다는 것을 알고 있습니다.

db.collection.update(  { _id:...} , { $set: someObjectWithNewData } 


답변

나는 내 자신의 기능으로 그것을 해결했다. 문서에서 지정된 필드를 업데이트하려면 명확하게 해결해야합니다.

예:

{
    _id : ...,
    some_key: { 
        param1 : "val1",
        param2 : "val2",
        param3 : "val3"
    }
}

param2 만 업데이트하려면 다음을 수행하십시오.

db.collection.update(  { _id:...} , { $set: { some_key : new_info  } }  //WRONG

다음을 사용해야합니다.

db.collection.update(  { _id:...} , { $set: { some_key.param2 : new_info  } } 

그래서 나는 그런 함수를 썼습니다 :

function _update($id, $data, $options=array()){

    $temp = array();
    foreach($data as $key => $value)
    {
        $temp["some_key.".$key] = $value;
    } 

    $collection->update(
        array('_id' => $id),
        array('$set' => $temp)
    );

}

_update('1', array('param2' => 'some data'));


답변

점 표기법을 사용하여 객체의 다른 속성에 영향을주지 않고 객체 내부의 필드에 액세스하고 설정할 수 있습니다.

위에서 지정한 객체가 주어지면 :

> db.test.insert({"id": "test_object", "some_key": {"param1": "val1", "param2": "val2", "param3": "val3"}})
WriteResult({ "nInserted" : 1 })

우리는 단지 업데이트 할 수 있습니다 some_key.param2some_key.param3:

> db.test.findAndModify({
... query: {"id": "test_object"},
... update: {"$set": {"some_key.param2": "val2_new", "some_key.param3": "val3_new"}},
... new: true
... })
{
    "_id" : ObjectId("56476e04e5f19d86ece5b81d"),
    "id" : "test_object",
    "some_key" : {
        "param1" : "val1",
        "param2" : "val2_new",
        "param3" : "val3_new"
    }
}

원하는만큼 깊이 파고들 수 있습니다. 또한 기존 속성에 영향을주지 않고 객체에 새 속성을 추가 할 때 유용합니다.


답변

가장 좋은 해결책은 객체에서 속성을 추출하여 평평한 점 표기법 키-값 쌍으로 만드는 것입니다. 예를 들어이 라이브러리를 사용할 수 있습니다.

https://www.npmjs.com/package/mongo-dot-notation

그것은이 .flatten필요없이 기존 DB 객체의 속성이 될 것이라고 우려 삭제 / 덮어 쓰기하지 않고, 당신이 다음 $ 설정 수정에 제공 될 수있는 성질의 평면 집합으로 개체를 변경할 수있는 기능.

mongo-dot-notation문서 에서 가져온 것 :

var person = {
  firstName: 'John',
  lastName: 'Doe',
  address: {
    city: 'NY',
    street: 'Eighth Avenu',
    number: 123
  }
};



var instructions = dot.flatten(person)
console.log(instructions);
/*
{
  $set: {
    'firstName': 'John',
    'lastName': 'Doe',
    'address.city': 'NY',
    'address.street': 'Eighth Avenu',
    'address.number': 123
  }
}
*/

그런 다음 완벽한 선택자를 형성합니다. 주어진 속성 만 업데이트합니다. 편집 : 나는 몇 번 고고학자가되고 싶다.)


답변

Mongo를 사용하면 .규칙을 사용하여 중첩 문서를 업데이트 할 수 있습니다 . 보세요 : MongoDB의 중첩 된 문서를 업데이트 . 다음은 내가 생각하는 것과 같은 병합 업데이트에 대한 과거의 또 다른 질문입니다. ‘병합’문서를 통한 MongoDB 원자 업데이트


답변

나는 이런 식으로 성공했다 :

db.collection.update(  { _id:...} , { $set: { 'key.another_key' : new_info  } } );

프로필 업데이트를 동적으로 처리하는 기능이 있습니다

function update(prop, newVal) {
  const str = `profile.${prop}`;
  db.collection.update( { _id:...}, { $set: { [str]: newVal } } );
}

참고 : ‘profile’은 구현에 따라 다르며 수정하려는 키 문자열입니다.


답변

원하는 것을 달성 할 수있는 isPartialObject 를 설정할 수있는 것처럼 보입니다 .