238

このドキュメントが MongoDB に保存されているとします。

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

外界param2との間の新しい情報を含むオブジェクトを保存する必要がありますparam3

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 に新しいフィールドのみを更新させる方法は何ですか (1 つずつ明示的に記述せずに)? これを取得するには:

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

私はJavaクライアントを使用していますが、どんな例でも大歓迎です

4

19 に答える 19

128

独自の関数で解決しました。ドキュメント内の指定されたフィールドを更新する場合は、明確に対処する必要があります。

例:

{
    _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'));
于 2013-04-20T10:14:32.387 に答える
119

私が質問を正しく理解していれば、別のドキュメントの内容でドキュメントを更新したいと考えていますが、まだ存在していないフィールドのみを更新し、既に設定されているフィールドを完全に無視します (別の値であっても)。

単一のコマンドでそれを行う方法はありません。

最初にドキュメントにクエリを実行し、必要なものを把握してから$set更新する必要があります (古い値を一致するフィルターとして使用して、その間に同時更新が行われないようにします)。


あなたの質問の別の読み方は、あなたは満足しているが$set、すべてのフィールドを明示的に設定したくないということです。その場合、どのようにデータを渡しますか?

次のことができることを知っています。

db.collection.update(  { _id:...} , { $set: someObjectWithNewData } 
于 2012-04-24T01:37:18.550 に答える
12

Mongo では、.規則を使用してネストされたドキュメントを更新できます。ご覧ください: mongodb でネストされたドキュメントを更新しています。マージ更新に関する過去の別の質問を次に示します。たとえば、あなたが探しているものと同様です: 「マージ」ドキュメントによる MongoDB アトミック更新

于 2012-04-24T01:40:12.720 に答える
11

Mongo 4.2db.collection.updateMany()(または)で始まるdb.collection.update()集計パイプラインを受け入れることができます。これにより、 などの集計演算子を使用できます。これにより$addFields、入力ドキュメントから既存のすべてのフィールドと新しく追加されたフィールドが出力されます。

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

// { some_key: { param1: "val1", param2: "val2", param3: "val3" } }
// { some_key: { param1: "val1", param2: "val2"                 } }
db.collection.updateMany({}, [{ $addFields: { some_key: new_info } }])
// { some_key: { param1: "val1", param2: "val2_new", param3: "val3_new" } }
// { some_key: { param1: "val1", param2: "val2_new", param3: "val3_new" } }
  • 最初の部分{}は一致クエリで、更新するドキュメント (この場合はすべてのドキュメント) をフィルタリングします。

  • 2 番目の部分[{ $addFields: { some_key: new_info } }]は、更新集計パイプラインです。

    • 集約パイプラインの使用を示す角括弧に注意してください。
    • これは集約パイプラインなので、 を使用できます$addFields
    • $addFields必要なことを正確に実行します。新しいオブジェクトが既存のオブジェクトとオーバーレイ/マージするようにオブジェクトを更新します。
    • この場合、はそのまま{ param2: "val2_new", param3: "val3_new" }にして既存のものにマージされ、と の両方を追加または置換します。some_keyparam1param2param3
于 2019-06-14T19:35:43.373 に答える
8

私はこのようにして成功しました:

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 } } );
}

注:「プロファイル」は私の実装に固有のものであり、変更したいキーの文字列にすぎません。

于 2016-07-24T16:48:52.507 に答える
3

$mergeObjects集計ベースの更新で使用できます。何かのようなもの

db.collection.update(
   { _id:...},
   [{"$set":{
      "some_key":{
        "$mergeObjects":[
          "$some_key",
          new info or { param2 : "val2_new", param3 : "val3_new"}
       ]
      }
   }}]
)

その他の例here

于 2020-11-25T15:03:08.370 に答える
2

あなたが望むものを達成するかもしれないisPartialObjectを設定できるようです。

于 2012-04-24T01:41:52.503 に答える
2
db.collection.update(  { _id:...} , { $set: { some_key : new_info  } } 

db.collection.update( { _id: ..} , { $set: { some_key: { param1: newValue} } } ); 

この助けを願っています!

于 2019-11-23T03:44:10.537 に答える
0

オブジェクトの複数のフィールドを更新したい場合は、これを試すことができます:-

 let fieldsToUpdate = {};
 for (const key in allFields) {
 const fieldName = `flags.${key}`;   // define field as string literal
     fieldsToUpdate[fieldName] = allFields[key];
 }
 db.collection.updateOne(query, { $set: { ...fieldsToUpdate } } );
于 2021-11-23T15:08:57.087 に答える
0

必要なドット パスを含むプロパティ名で更新オブジェクトを作成します。(「somekey。」+ OPの例から)、それを使用して更新を行います。

//the modification that's requested
updateReq = { 
   param2 : "val2_new",
   param3 : "val3_new"   
}

//build a renamed version of the update request
var update = {};
for(var field in updateReq){
    update["somekey."+field] = updateReq[field];
}

//apply the update without modifying fields not originally in the update
db.collection.update({._id:...},{$set:update},{upsert:true},function(err,result){...});
于 2018-06-08T23:23:17.757 に答える