はじめに
この実験では、MongoDB コレクション内のドキュメントを更新する方法を学びます。まず、updateOne() メソッドを使用して単一のドキュメントを変更します。次に、updateMany() メソッドを使用して複数のドキュメントを一度に変更する方法を学びます。また、特定の変更を行うために $set、$inc、$unset などのさまざまな更新演算子を使用します。最後に、既存のドキュメントを更新するか、存在しない場合は新しいドキュメントを作成できる upsert オプションについて説明します。この実験は、MongoDB における基本的なデータ操作スキルを習得するための実践的なアプローチを提供します。
updateOne を使用した単一ドキュメントの更新
このステップでは、MongoDB コレクション内の単一ドキュメントを変更する方法を学びます。updateOne() メソッドと $set 演算子を組み合わせて、特定のドキュメントのフィールド値を変更します。
まず、MongoDB シェルを開いてデータベースにアクセスします。
mongosh
シェルに入ったら、準備された mylab_database に切り替えます。
use mylab_database
books コレクション内の現在のドキュメントを表示しましょう。.pretty() メソッドは、出力をより読みやすくフォーマットします。
db.books.find().pretty();
3 つの初期の書籍ドキュメントが表示されるはずです。_id の値は、お使いの環境で一意になります。
[
{
_id: ObjectId("..."),
title: 'JavaScript Fundamentals',
author: 'Mike Johnson',
year: 2022,
pages: 350
},
{
_id: ObjectId("..."),
title: 'Python Deep Dive',
author: 'Sarah Williams',
year: 2021,
pages: 450
},
{
_id: ObjectId("..."),
title: 'Machine Learning Basics',
author: 'John Doe',
year: 2020,
price: 39.99
}
]
次に、「JavaScript Fundamentals」というタイトルの書籍の出版年を 2023 に更新しましょう。
db.books.updateOne(
{ title: "JavaScript Fundamentals" },
{ $set: { year: 2023 } }
);
このコマンドの内訳を見てみましょう。
updateOne(): このメソッドは、フィルターに一致する最初のドキュメントを見つけて更新します。{ title: "JavaScript Fundamentals" }: これはフィルタードキュメントです。MongoDB に対して、titleフィールドが "JavaScript Fundamentals" であるドキュメントを見つけるように指示します。{ $set: { year: 2023 } }: これは更新ドキュメントです。$set演算子は、yearフィールドの値を2023に置き換えます。
コマンドは、操作を確認する結果オブジェクトを返します。
{
"acknowledged": true,
"insertedId": null,
"matchedCount": 1,
"modifiedCount": 1,
"upsertedCount": 0
}
matchedCount: 1 はフィルターに一致したドキュメントが 1 つあったことを示し、modifiedCount: 1 はドキュメントが 1 つ正常に更新されたことを示しています。
変更を確認するために、再度ドキュメントを検索します。
db.books.findOne({ title: "JavaScript Fundamentals" });
出力には、新しい年で更新されたドキュメントが表示されます。
{
_id: ObjectId("..."),
title: 'JavaScript Fundamentals',
author: 'Mike Johnson',
year: 2023,
pages: 350
}
updateMany を使用した複数ドキュメントの更新
時には、複数のドキュメントを一度に更新する必要がある場合があります。このために、MongoDB は updateMany() メソッドを提供します。このステップでは、特定の年より前に発行されたすべての書籍に新しいフィールドを追加します。
2022 年より前に発行されたすべての書籍に、値 "Classic" を持つ status フィールドを追加しましょう。
db.books.updateMany({ year: { $lt: 2022 } }, { $set: { status: "Classic" } });
コマンドの説明は以下の通りです。
updateMany(): このメソッドは、指定されたフィルターに一致するすべてのドキュメントを更新します。{ year: { $lt: 2022 } }: このフィルターは、yearが2022より小さいドキュメントを選択します。$lt演算子は「less than」(より小さい)を表します。{ $set: { status: "Classic" } }: この更新ドキュメントは、一致したすべてのドキュメントに値"Classic"を持つ新しいフィールドstatusを追加します。
出力には、いくつのドキュメントが一致し、変更されたかが表示されます。この場合、2 冊の書籍が 2022 年より前に発行されています。
{
"acknowledged": true,
"insertedId": null,
"matchedCount": 2,
"modifiedCount": 2,
"upsertedCount": 0
}
両方のドキュメントが更新されたことを確認するには、ステータスが "Classic" のすべての書籍をクエリします。
db.books.find({ status: "Classic" }).pretty();
status フィールドが含まれるようになった 2 冊の書籍が表示されます。
[
{
_id: ObjectId("..."),
title: 'Python Deep Dive',
author: 'Sarah Williams',
year: 2021,
pages: 450,
status: 'Classic'
},
{
_id: ObjectId("..."),
title: 'Machine Learning Basics',
author: 'John Doe',
year: 2020,
price: 39.99,
status: 'Classic'
}
]
更新演算子 $inc および $unset の使用
MongoDB は、さまざまな種類の更新に対応する多様な演算子を提供しています。このステップでは、数値フィールドを増減させる $inc と、ドキュメントからフィールドを削除する $unset の使用方法を学びます。
まず、$inc 演算子を使用して、「Python Deep Dive」というタイトルの書籍のページ数を 50 増加させましょう。$inc 演算子は、指定された値だけフィールドをインクリメントします。
db.books.updateOne({ title: "Python Deep Dive" }, { $inc: { pages: 50 } });
変更を確認するために、ドキュメントを取得します。
db.books.findOne({ title: "Python Deep Dive" });
pages フィールドは、現在 500(450 + 50)になっているはずです。
{
_id: ObjectId("..."),
title: 'Python Deep Dive',
author: 'Sarah Williams',
year: 2021,
pages: 500,
status: 'Classic'
}
次に、「Machine Learning Basics」というタイトルのドキュメントから price フィールドを削除しましょう。$unset 演算子は、特定のフィールドを削除します。$unset に提供される値(この場合は "")は重要ではなく、任意の値を使用できます。
db.books.updateOne(
{ title: "Machine Learning Basics" },
{ $unset: { price: "" } }
);
price フィールドが削除されたことを確認しましょう。
db.books.findOne({ title: "Machine Learning Basics" });
出力には、price フィールドのないドキュメントが表示されます。
{
_id: ObjectId("..."),
title: 'Machine Learning Basics',
author: 'John Doe',
year: 2020,
status: 'Classic'
}
upsert を使用したドキュメントの作成
「upsert」(アップサート)は、ドキュメントが存在する場合は更新し、存在しない場合は新規挿入する特殊な更新操作です。「チェックしてから挿入」という別々のロジックを回避し、データベース操作のアトミック性を保証するのに役立ちます。アップサートは、特に以下のようなシナリオで非常に有用です。
- データの一貫性の保証: ドキュメントの存在を最初に確認してから挿入または更新を決定する代わりに、単一の操作で両方のケースをアトミックに処理できます。
- 並行操作の処理: マルチユーザー環境において、アップサートは、チェックと挿入操作の間に別のプロセスが同じドキュメントを挿入してしまう競合状態 (race condition) を防ぎます。
- アプリケーションロジックの簡素化: アプリケーションコード内の複雑な条件付きロジックの必要性を減らし、保守性を高め、エラー発生のリスクを低減します。
この動作を有効にするには、更新コマンドに upsert: true オプションを追加します。
新しい書籍「Cloud Computing Essentials」を追加してみましょう。この書籍はコレクションに存在しないため、upsert 操作によって作成されます。
db.books.updateOne(
{ title: "Cloud Computing Essentials" },
{ $set: { author: "David Lee", year: 2023, pages: 300 } },
{ upsert: true }
);
このコマンドは 3 つの部分で構成されています。
- フィルター:
{ title: "Cloud Computing Essentials" } - 更新操作:
{ $set: { ... } } - オプション:
{ upsert: true }
フィルターに一致するドキュメントがなかったため、新しいドキュメントが作成されました。結果オブジェクトには upsertedId が含まれることで、これが反映されます。
{
acknowledged: true,
matchedCount: 0,
modifiedCount: 0,
upsertedCount: 1,
upsertedId: ObjectId("...")
}
同じコマンドをもう一度実行してみましょう。今度は、MongoDB は先ほど作成したドキュメントを見つけ、それを更新します。
db.books.updateOne(
{ title: "Cloud Computing Essentials" },
{ $set: { author: "David Lee", year: 2023, pages: 300 } },
{ upsert: true }
);
結果は matchedCount: 1 と表示されます。設定しているデータが既存のデータと同じであるため、modifiedCount は 0 です。もし値を変更していれば、modifiedCount は 1 になります。
{
"acknowledged": true,
"insertedId": null,
"matchedCount": 1,
"modifiedCount": 0,
"upsertedCount": 0
}
新しい書籍がコレクションに存在することを確認できます。
db.books.findOne({ title: "Cloud Computing Essentials" });
出力には、新しく作成されたドキュメントが表示されます。
{
_id: ObjectId("..."),
title: 'Cloud Computing Essentials',
author: 'David Lee',
year: 2023,
pages: 300
}
作業が完了したら、MongoDB Shell を終了できます。
exit;
まとめ
この実験では、MongoDB でドキュメントを更新するための基本的なテクニックを学びました。updateOne を使用して単一のドキュメントを更新する方法と、updateMany を使用して複数のドキュメントを更新する方法を実践しました。また、フィールド値を変更するための $set、数値を増減させるための $inc、フィールドを削除するための $unset など、強力な更新演算子についても学びました。最後に、ドキュメントが存在しない場合に作成するための upsert オプションの使用方法を学びました。これらのスキルは、あらゆる MongoDB アプリケーションでデータを管理および維持するための基本となります。

