MongoDBでフィールドの値をその値自身を使って更新する方法
MongoDBでは、通常の$set演算子ではフィールドの現在の値を直接参照して更新することができません。フィールド自身の値を利用して新しい値を設定したい場合は、集計パイプライン(Aggregation Pipeline)を使ったアップデートが有効です。本記事では、具体的な手順をサンプルコードとともに解説します。
コレクションの作成
まず、ドキュメントを含むコレクションを作成しましょう。
> db.demo256.insertOne({"Name":"Chris"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e47a3e91627c0c63e7dba8b")
}
> db.demo256.insertOne({"Name":"Bob"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e47a3ea1627c0c63e7dba8c")
}
> db.demo256.insertOne({"Name":"David"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e47a3eb1627c0c63e7dba8d")
}ドキュメントの表示
find()メソッドを使用して、コレクション内のすべてのドキュメントを表示します。
> db.demo256.find();
実行すると、次のような出力が得られます。
{ "_id" : ObjectId("5e47a3e91627c0c63e7dba8b"), "Name" : "Chris" }
{ "_id" : ObjectId("5e47a3ea1627c0c63e7dba8c"), "Name" : "Bob" }
{ "_id" : ObjectId("5e47a3eb1627c0c63e7dba8d"), "Name" : "David" }$setだけでは元の値を参照できない点に注意
たとえば、次のように単純に$setを使ったとします。
> db.demo256.update({}, {$set:{"Name":"Name" + " is a student"}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })この場合、「"Name" + " is a student"」はシェル側のJavaScriptとして先に評価されるため、結果的にはリテラル文字列「Name is a student」がそのままセットされるだけです。既存のフィールド値(Chrisなど)は参照されず、元の値を利用した更新にはなりません。
集計パイプラインでフィールド自身の値を参照する
フィールドの現在の値を参照しながら更新するには、更新操作に集計パイプラインを渡します。$concatなどの演算子と組み合わせることで、既存の値をもとに新しい値を生成できます。
> db.demo256.updateMany({},
[ { $set: { "Name": { $concat: [ "$Name", " is a student" ] } } } ]
);
{ "acknowledged" : true, "matchedCount" : 3, "modifiedCount" : 3 }ポイントは次の3つです。
- 第2引数を配列形式にすると、集計パイプラインとして扱われます。
- 「
$Name」のようにフィールド名の前に$を付けると、そのフィールドの現在の値を参照できます。 $concat演算子により、既存の名前に文字列を連結した新しい値が設定されます。
更新結果の確認
もう一度find()メソッドを実行して、すべてのドキュメントを表示してみましょう。
> db.demo256.find();
実行すると、次のような出力が得られます。
{ "_id" : ObjectId("5e47a3e91627c0c63e7dba8b"), "Name" : "Chris is a student" }
{ "_id" : ObjectId("5e47a3ea1627c0c63e7dba8c"), "Name" : "Bob is a student" }
{ "_id" : ObjectId("5e47a3eb1627c0c63e7dba8d"), "Name" : "David is a student" }各ドキュメントのNameフィールドが、元の値に「is a student」という文字列を連結した形で更新されていることが確認できます。
まとめ
- 通常の
$setでは、フィールド自身の値を参照して更新することはできません。 - 配列形式(集計パイプライン)のアップデートと
$concatなどを組み合わせれば、既存の値を利用した更新が可能です。 - 数値の加算・減算には
$addや$subtractなども同様に使えます。
-
MongoDBでforEach()を使って特定の学生の点数を更新する方法
MongoDBでforEach()を使ってドキュメント内の点数を更新するこの記事では、forEach()メソッドを使ってコレクション内のドキュメントを走査し、学生名が「David」のドキュメントを見つけて、その学生の点数(Marks)を新しい値に更新する方法を解説します。1. コレクションとドキュメントを作成するまず、insertOne()メソッドを使ってサンプル用のコレクションにドキュメントを作成しましょう。> db.demo634.insertOne({Name:Chris,Marks:76}); { acknowledged : true, insertedId :
-
MongoDBでサブコレクション(ネストされたドキュメント)を更新する方法
MongoDBでは、ネストされたドキュメント(サブコレクション)の配列に要素を追加したい場合、update()メソッドと$push演算子を組み合わせて使用します。ドット記法(dot notation)を使うことで、サブドキュメント内の特定のフィールドに直接アクセスし、値を追加することができます。ドキュメントを含むコレクションを作成するまず、サンプルとなるコレクションにドキュメントを挿入してみましょう。> db.demo547.insertOne( ... { ... Name : Chris, ... Test : ... { ... FirstTest :