こんにちは、かつコーチです。
前回はドキュメントとBSONの基礎を解説しました。
今回はいよいよ実践編として、MongoDBのCRUD操作(Create・Read・Update・Delete、データの作成・読み取り・更新・削除)をmongoshで一通り実行してみます。
SQLのINSERT・SELECT・UPDATE・DELETEに相当する操作ですが、構文の見た目はかなり異なります。
1つずつ対応関係を確認しながら進めましょう。
Create:ドキュメントを作成する
insertOneとinsertMany
1件だけ挿入する場合はinsertOne、複数件まとめて挿入する場合はinsertManyを使います。
SQLのINSERT INTOに相当する操作です。
// 1件挿入(SQLの INSERT INTO users (...) VALUES (...) に相当)
db.users.insertOne({
name: "田中太郎",
age: 28,
email: "tanaka@example.com",
status: "active"
})
// 複数件まとめて挿入
db.users.insertMany([
{ name: "佐藤花子", age: 25, email: "sato@example.com", status: "active" },
{ name: "鈴木一郎", age: 34, email: "suzuki@example.com", status: "inactive" }
])
insertOneが成功すると、自動生成された_id(ObjectId)を含むレスポンスが返ってきます。
SQLのAUTO_INCREMENTと違い、事前にIDを採番するテーブル設定は不要です。
Read:ドキュメントを検索する
findとfindOneの基本
検索にはfind(複数件)とfindOne(1件のみ)を使います。
SQLのSELECT * FROM users WHERE ...に相当する操作です。
// 全件取得(SQLの SELECT * FROM users に相当)
db.users.find()
// 条件を指定して検索(SQLの WHERE status = 'active' に相当)
db.users.find({ status: "active" })
// 1件だけ取得
db.users.findOne({ name: "田中太郎" })
取得するフィールドを絞り込む(射影)
SQLのSELECT name, email FROM usersのように、特定のカラムだけ取得したい場合は、第2引数に射影(プロジェクション)を指定します。
// name と email だけを取得する(_id はデフォルトで含まれる)
db.users.find(
{ status: "active" },
{ name: 1, email: 1 }
)
// _id も除外したい場合は 0 を指定する
db.users.find(
{ status: "active" },
{ name: 1, email: 1, _id: 0 }
)
1は「含める」、0は「除外する」という意味です。
このあたりの発想はSQLのカラム指定と近く、初心者でも比較的すんなり理解できるはずです。
検索結果を整形する(ソート・件数制限)
SQLのORDER BY・LIMITに相当するメソッドも用意されています。
// age の降順で並び替え、上位5件だけ取得
// SQLの ORDER BY age DESC LIMIT 5 に相当
db.users.find().sort({ age: -1 }).limit(5)
sortには1(昇順)か-1(降順)を指定します。
メソッドを.でつなげて書けるのがmongoshの特徴で、SQLのように1つの文にすべて詰め込む必要がありません。
Update:ドキュメントを更新する
updateOneとupdateManyの基本
更新にはupdateOne(1件)・updateMany(複数件)を使います。
SQLのUPDATE users SET ... WHERE ...に相当しますが、更新内容は更新演算子という専用の記法で指定する点に注意が必要です。
// name が "田中太郎" のドキュメントの age を 29 に更新
// SQLの UPDATE users SET age = 29 WHERE name = '田中太郎' に相当
db.users.updateOne(
{ name: "田中太郎" },
{ $set: { age: 29 } }
)
$setは「指定したフィールドの値を更新する」という意味の更新演算子です。
これがないと、更新後のドキュメント全体をまるごと置き換える動作になってしまいます。
❌よくある失敗:$setを忘れてドキュメントが消える
私が初めてMongoDBの更新を試したとき、$setを付けずに次のように書いてしまい、他のフィールドがすべて消えてしまう事故を起こしたことがあります。
❌ Before:$setを付けずに更新すると、指定したフィールド以外が消える
db.users.updateOne(
{ name: "田中太郎" },
{ age: 29 }
)
// ageだけのドキュメントに置き換わってしまい、
// name・email・statusなど他のフィールドが全部消える
✅ After:$setを使い、指定フィールドだけを更新する
db.users.updateOne(
{ name: "田中太郎" },
{ $set: { age: 29 } }
)
// ageだけが更新され、他のフィールドはそのまま残る
SQLのUPDATEは「指定したカラムだけを変更する」のが当たり前の挙動なので、この違いに気づかず事故を起こす人は少なくありません。
更新するときは必ず$setを使う、と体で覚えておくのがおすすめです。
upsertオプション
「該当するドキュメントがあれば更新、なければ新規作成」という処理をしたい場合は、upsertオプションを使います。
// name が "山田次郎" のドキュメントがなければ新規作成する
db.users.updateOne(
{ name: "山田次郎" },
{ $set: { age: 40, status: "active" } },
{ upsert: true }
)
Delete:ドキュメントを削除する
deleteOneとdeleteMany
削除にはdeleteOne(1件)・deleteMany(複数件)を使います。
SQLのDELETE FROM users WHERE ...に相当します。
// status が "inactive" のドキュメントを1件だけ削除
db.users.deleteOne({ status: "inactive" })
// status が "inactive" のドキュメントを全件削除
db.users.deleteMany({ status: "inactive" })
条件を空オブジェクト{}にすると全件が対象になってしまうため、実行前には必ずfindで対象件数を確認する癖をつけましょう。
// 削除前に、まず対象件数を確認する習慣をつける
db.users.countDocuments({ status: "inactive" })
まとめ
この記事のポイント
- Create:
insertOne/insertManyでドキュメントを作成する - Read:
find/findOneで検索し、射影・sort・limitで絞り込みや整形ができる - Update:
updateOne/updateManyは$setを付けないとドキュメント全体が置き換わる事故につながる - Delete:
deleteOne/deleteManyは実行前にcountDocumentsで対象件数を確認すると安全 - SQLの
INSERT・SELECT・UPDATE・DELETEと対応関係を意識すると理解が早い
次に読むべき記事
基本のCRUDができるようになったら、次回は「クエリ演算子(gt・in・$regex等)の使い方」で、より複雑な条件検索の書き方を解説します。
タグ: MongoDB 初心者向け 基本操作