MongoDB
 Computer >> コンピューター >  >> プログラミング >> MongoDB

【MongoDB】upsertを使って値が一意の場合のみ挿入し、既存なら更新する方法

MongoDBではupsertを利用することで、「挿入しようとした値がすでに存在する場合は更新を行い、存在しない場合は新規に挿入する」という処理を1つの操作で実現できます。この仕組みは、重複データの管理やデータの同期処理などで非常に便利です。

upsertとは

upsertとは「update(更新)」と「insert(挿入)」を組み合わせた言葉で、update()メソッドに{ upsert: true }オプションを指定することで有効になります。条件に一致するドキュメントがあれば更新し、なければ新しいドキュメントとして挿入されます。

サンプルコレクションの作成

まず、ドキュメントを含むコレクションを作成しましょう。ここでは学生の名前と年齢を格納するコレクションを使用します。

> db.onlyInsertIfValueIsUniqueDemo.insertOne({"StudentName":"Larry","StudentAge":22});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c9a633815e86fd1496b38a4")
}
> db.onlyInsertIfValueIsUniqueDemo.insertOne({"StudentName":"Mike","StudentAge":21});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c9a634a15e86fd1496b38a5")
}
> db.onlyInsertIfValueIsUniqueDemo.insertOne({"StudentName":"Sam","StudentAge":24});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c9a635015e86fd1496b38a6")
}

登録済みドキュメントの確認

find()メソッドを使って、コレクション内のすべてのドキュメントを表示します。

> db.onlyInsertIfValueIsUniqueDemo.find().pretty();

実行すると以下の出力が得られます。

{
   "_id" : ObjectId("5c9a633815e86fd1496b38a4"),
   "StudentName" : "Larry",
   "StudentAge" : 22
}
{
   "_id" : ObjectId("5c9a634a15e86fd1496b38a5"),
   "StudentName" : "Mike",
   "StudentAge" : 21
}
{
   "_id" : ObjectId("5c9a635015e86fd1496b38a6"),
   "StudentName" : "Sam",
   "StudentAge" : 24
}

ケース1:値がすでに存在する場合(更新される)

既存の値に対してupsertを実行すると、挿入ではなく更新が行われます。ここでは「Mike」という学生の年齢を27に変更してみます。

> db.onlyInsertIfValueIsUniqueDemo.update({StudentName:"Mike"},{$set:{"StudentAge":27}},{ upsert: true});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

nMatched: 1nModified: 1が出力されていることから、既存ドキュメントが一致して更新されたことがわかります。再度すべてのドキュメントを確認してみましょう。

> db.onlyInsertIfValueIsUniqueDemo.find().pretty();
{
   "_id" : ObjectId("5c9a633815e86fd1496b38a4"),
   "StudentName" : "Larry",
   "StudentAge" : 22
}
{
   "_id" : ObjectId("5c9a634a15e86fd1496b38a5"),
   "StudentName" : "Mike",
   "StudentAge" : 27
}
{
   "_id" : ObjectId("5c9a635015e86fd1496b38a6"),
   "StudentName" : "Sam",
   "StudentAge" : 24
}

Mikeの年齢が21から27に更新されていることが確認できます。

ケース2:値が一意である場合(新規挿入される)

次に、まだ存在しない値「David」に対して同じクエリを実行します。この場合は該当ドキュメントがないため、新規挿入が行われます。

> db.onlyInsertIfValueIsUniqueDemo.update({StudentName:"David"},{$set:{"StudentAge":25}},{ upsert: true});
WriteResult({
   "nMatched" : 0,
   "nUpserted" : 1,
   "nModified" : 0,
   "_id" : ObjectId("5c9a654ce628c11759caea54")
})

nUpserted: 1と出力されているため、新しいドキュメントが挿入されたことがわかります。もう一度全ドキュメントを表示して確認します。

> db.onlyInsertIfValueIsUniqueDemo.find().pretty();
{
   "_id" : ObjectId("5c9a633815e86fd1496b38a4"),
   "StudentName" : "Larry",
   "StudentAge" : 22
}
{
   "_id" : ObjectId("5c9a634a15e86fd1496b38a5"),
   "StudentName" : "Mike",
   "StudentAge" : 27
}
{
   "_id" : ObjectId("5c9a635015e86fd1496b38a6"),
   "StudentName" : "Sam",
   "StudentAge" : 24
}
{
   "_id" : ObjectId("5c9a654ce628c11759caea54"),
   "StudentName" : "David",
   "StudentAge" : 25
}

まとめ

{ upsert: true }オプションを使うことで、MongoDBにおいて「存在すれば更新、存在しなければ挿入」という動作を簡単に実装できます。WriteResultの出力内容を見ることで、更新と挿入のどちらが行われたかも判別可能です。

  • nMatched:条件に一致した既存ドキュメントの数
  • nModified:実際に変更されたドキュメントの数
  • nUpserted:新規に挿入されたドキュメントの数

なお、最新のMongoDBではupdateOne()updateMany()、あるいはreplaceOne()メソッドでも同様にupsertオプションが利用できるため、非推奨となっている旧式のupdate()の代わりにこれらのメソッドを使用することをおすすめします。

  1. MongoDBでドキュメントの値を1つだけインクリメントする方法

    MongoDBでドキュメント内の特定の値だけを更新し、インクリメント(加算)したい場合は、update()メソッドと$inc演算子を組み合わせて使用します。$incは指定したフィールドの数値を増減させるための演算子で、他のフィールドに影響を与えることなくピンポイントで値を変更できるのが特徴です。サンプルコレクションの作成まず、ドキュメントを格納したコレクションを作成します。> db.demo698.insertOne({Score:78});{   "acknowledged" : true,   "insertedI

  2. MySQLで単一の列(カラム)の値のみを更新する方法

    MySQLでは、UPDATE文を使うことで、テーブル内の特定の列(カラム)の値だけを簡単に更新できます。この記事では、サンプルテーブルを作成し、単一の列の値のみを更新する手順を具体例とともにわかりやすく解説します。 1. サンプルテーブルの作成 まず、テーブルを作成しましょう。 mysql> create table DemoTable1605 -> ( -> StudentId int NOT NULL AUTO_INCREMENT PRIMARY KEY, -> StudentName varchar(20), -> Stude