本文へスキップ
totonoe.tech

プログラミング言語を整える

中級

MongoDB を整える。

= 表ではなくドキュメントで持つ MongoDB を、find と aggregate を動かしながら学ぶ

MongoDB が初めての方は、先に そもそも MongoDB とは・どんな場面で使うか をどうぞ。

MongoDBとは

データを表の行ではなく JSON に似た「ドキュメント」として保存するデータベースで、Web やアプリのバックエンドでよく使われています。

誕生 2009年(10gen 社が開発を始め、同社は2013年に社名を MongoDB 社に改めました)
作った人・組織 10gen 社(Dwight Merriman、Eliot Horowitz ら)。現在は MongoDB 社が開発しています
種類 ドキュメント指向データベース(NoSQL)
ライセンス SSPL(Server Side Public License)。2018年から。それ以前は AGPL(GNU Affero General Public License)でした。SSPL は OSI が認めたオープンソースライセンスではありません
得意なこと 入れ子のオブジェクトや配列を持つデータを1件のドキュメントとしてそのまま保存でき、決まった表の形(スキーマ)を先に作らなくても書き込めることです。
手元で動かすには mongosh

日本での使われ方

  • Web サービスやスマートフォンアプリのバックエンドで、アプリケーションのデータを保存する先として使われています。
  • 項目が増えたり減ったりしやすいデータを、表の定義を変えずに保存したい場面で選ばれます。
  • アクセスログや操作の記録(イベント)のように、形が少しずつ違うデータを大量にためる用途にも使われます。
  • センサーや機器から送られてくる IoT のデータを、機器ごとの違いを残したまま保存する例もあります。

使えるクラウドサービス

  • MongoDB Atlas:MongoDB 社自身が提供するクラウドサービスで、AWS・Google Cloud・Microsoft Azure の上に MongoDB を作れます。
  • Amazon DocumentDB(MongoDB 互換):AWS が提供するドキュメントデータベースです。MongoDB の API と互換がありますが、MongoDB そのものではなく、対応していない機能もあります。
  • Azure Cosmos DB for MongoDB:Microsoft Azure の Cosmos DB を、MongoDB 互換の API で使えるようにしたものです。こちらも MongoDB そのものではありません。

研修・学習での位置づけ

MongoDB は、RDB の次に「表を使わないデータベース(NoSQL)」の考え方を学ぶ題材として使われます。問い合わせは SQL ではなく、JavaScript のオブジェクトに似た書き方で条件や集計の手順(パイプライン)を書きます。このページの練習場は MongoDB 本体ではなく、問い合わせを JavaScript で再現したものです。本物の MongoDB では、フィールドの並びや数値の型(整数か小数か)の表示など、細かいところが違うことがあります。

関わる資格

  • MongoDB Associate Developer(MongoDB University。アプリケーションから MongoDB を使う開発者向けの認定)
  • MongoDB Associate Database Administrator(MongoDB University。MongoDB の運用管理の認定)

ブラウザでMongoDBを動かす

mongosh に打つ db.コレクション.メソッド(…) を、このページの中で再現して動かします。本物の MongoDB ではありません。書いたコードは端末の外には出ません。

MongoDB 再現(mingo 7.2.5)・本物の MongoDB ではありません

結果

「実行」を押すと、準備のデータ(下の「準備(全お題共通)」)を入れてから、エディタのコードを流します。

この練習場でできること・できないこと
  • 本物の MongoDB ではなく、問い合わせ(find の条件・射影・並べ替え)と集計のパイプライン(aggregate)を mingo で再現したものです。
  • 使えるのは insertOne・insertMany・find・findOne・countDocuments・distinct・updateOne・updateMany・replaceOne・deleteOne・deleteMany・aggregate・drop・createIndex です。インデックスは作った名前を返すだけで、速さは変わりません。
  • 表示は mongosh に寄せていますが、1件を1行で出すなど細部は本物と違います。フィールドの並びや数値の型(int と double の区別)も本物と同じとは限りません。
  • JavaScript としては実行しません(const や関数、ループは使えません)。データはこのページを開いている間だけ続きます。

そもそも MongoDB とは

表ではなく、入れ子の文書(ドキュメント)をそのまま保存するデータベース。

MongoDB(モンゴディービー)は、SQL を使わないNoSQLのうち、ドキュメント指向と呼ばれるデータベースです。JSON に近い形のデータ(内部的には BSON という形式)を、一件ずつの「ドキュメント」として保存します。表の列をあらかじめ細かく決めなくてもよく、データの形が変わりやすいアプリで使われます。

リレーショナルデータベース(RDB)は、データを複数の表に分けて、JOIN で結び付けます。MongoDB は、関連するデータを入れ子にして一か所にまとめて持つ考え方です。Redis のようにキーと値だけを素早く扱うデータベースとも違います。

どこで・どんな場面で使うか

  • Web・モバイルアプリの裏側

    ユーザーごとに項目が違う設定や、頻繁に仕様が変わるデータの保存に使われます。

  • 商品カタログ・コンテンツ

    商品ごとに属性が違うデータを、一件のドキュメントにまとめて持てます。

  • ログ・イベントの保存

    形がそろっていない記録を、そのまま溜めておく用途にも使われます。

  • クラウドのサービス

    MongoDB 社の MongoDB Atlas をはじめ、運用を任せられるサービスがあります。

  • 求人での位置づけ

    Node.js などの Web 開発の募集で、使える技術として名前が出ます。

向いている場面・向いていない場面

  • 向いている場面:データの形が変わりやすい、入れ子の構造をそのまま保存したい、まず素早く作り始めたいアプリ。
  • 向いていない場面:複数の表を何度も結び付けて集計する用途。こちらは RDB と SQL のほうが書きやすいことが多いです。
  • 使い分けが大事。NoSQL は RDB の代わりではなく、場面に応じて選ぶ別の道具です。

上の練習場では、MongoDB の問い合わせの動きをブラウザの中で再現して試せます(本物の MongoDB ではありません)。下のお題のコマンドを流して、結果を確かめてみてください。

6つのお題をMongoDBで書く

PostgreSQL・MySQL・DuckDB・MongoDB・Redis の5ページで、同じ商品と注文のデータに同じ6つのお題を並べています。SQL の方言の違いや、SQL を使わないデータベースでの考え方の違いがそのまま比べられます。

上の練習場は本物の MongoDB ではなく、問い合わせの動きを mingo(MongoDB の問い合わせ言語の JavaScript 実装)で再現したものです。この環境では MongoDB 本体を動かせなかったため、表示している結果は再現の出力で、mongosh の表示に寄せた形です。フィールドの並びや数値の型などの細部は、本物と違うことがあります。

準備(全お題共通)データを入れるコード。お題2〜6・クイズ・エラーの例は、これを流した後に続けて流した結果です。
db.products.insertMany([
  { _id: 1, name: 'りんご', category: '果物', price: 150 },
  { _id: 2, name: 'みかん', category: '果物', price: 80 },
  { _id: 3, name: '牛乳', category: '飲み物', price: 200 },
  { _id: 4, name: 'お茶', category: '飲み物', price: 120 },
  { _id: 5, name: '食パン', category: 'パン', price: 250 }
])
db.orders.insertMany([
  { _id: 1, product_id: 1, qty: 3, ordered_on: ISODate('2026-10-01') },
  { _id: 2, product_id: 3, qty: 1, ordered_on: ISODate('2026-10-01') },
  { _id: 3, product_id: 2, qty: 5, ordered_on: ISODate('2026-10-02') },
  { _id: 4, product_id: 1, qty: 2, ordered_on: ISODate('2026-10-03') },
  { _id: 5, product_id: 4, qty: 4, ordered_on: ISODate('2026-10-03') }
])

mongosh

db.products.insertMany([
  { _id: 1, name: 'りんご', category: '果物', price: 150 },
  { _id: 2, name: 'みかん', category: '果物', price: 80 },
  { _id: 3, name: '牛乳', category: '飲み物', price: 200 },
  { _id: 4, name: 'お茶', category: '飲み物', price: 120 },
  { _id: 5, name: '食パン', category: 'パン', price: 250 }
])
db.orders.insertMany([
  { _id: 1, product_id: 1, qty: 3, ordered_on: ISODate('2026-10-01') },
  { _id: 2, product_id: 3, qty: 1, ordered_on: ISODate('2026-10-01') },
  { _id: 3, product_id: 2, qty: 5, ordered_on: ISODate('2026-10-02') },
  { _id: 4, product_id: 1, qty: 2, ordered_on: ISODate('2026-10-03') },
  { _id: 5, product_id: 4, qty: 4, ordered_on: ISODate('2026-10-03') }
])
db.products.find()

結果

{
  acknowledged: true,
  insertedIds: { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }
}
{
  acknowledged: true,
  insertedIds: { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }
}
[
  { _id: 1, name: 'りんご', category: '果物', price: 150 },
  { _id: 2, name: 'みかん', category: '果物', price: 80 },
  { _id: 3, name: '牛乳', category: '飲み物', price: 200 },
  { _id: 4, name: 'お茶', category: '飲み物', price: 120 },
  { _id: 5, name: '食パン', category: 'パン', price: 250 }
]

MongoDB には CREATE TABLE に当たる準備が要らず、コレクション(表に当たるもの)は最初にドキュメントを入れたときに作られます。ドキュメントごとに項目が違っていても入れられます。_id は必ず付く主キーで、書かなければ ObjectId が自動で振られますが、ここでは結果をそろえるため番号を自分で入れています。

同じお題をほかのデータベースで: PostgreSQL・MySQL・DuckDB・Redis

出力当てクイズ

準備のデータを入れた後に流したときの、最後のコマンドの結果を選んでください。選ぶと正解と理由が出ます(答えはどこにも送られず、記録もしません)。

問1

db.products.countDocuments({ category: '果物', price: { $lt: 100 } })

画面に出るのは?

問2

db.products.findOne({ price: { $lt: 100 } }, { _id: 0, name: 1 })

画面に出るのは?

問3

db.products.updateMany({ category: '飲み物' }, { $inc: { price: 10 } })
db.products.findOne({ _id: 4 }, { _id: 0, price: 1 })

画面に出るのは?

問4

db.products.distinct('category')

画面に出るのは?

よくあるエラーと直し方

書き始めの人が出会いやすいエラーです。メッセージは英語のまま出るので、どの言葉を手がかりにすればよいかもあわせて載せています。

同じ _id で入れようとした

エラーになるコード

db.products.insertOne({ _id: 1, name: 'ぶどう', category: '果物', price: 400 })

画面に出るメッセージ(抜粋)

MongoServerError: E11000 duplicate key error collection: test.products index: _id_ dup key: { _id: 1 }

何が起きているか:_id はコレクションの中で重ならないことが保証される主キーで、自動で一意のインデックス(_id_)が付いています。_id: 1 のりんごが既にあるため、入れられませんでした。

直し方:新しい _id を使うか、_id を書かずに入れて ObjectId を自動で振らせます。既にあるものを書き換えたいときは updateOne や replaceOne を使います。

演算子の綴りを間違えた

エラーになるコード

db.products.find({ price: { $gtt: 100 } })

画面に出るメッセージ(抜粋)

MongoServerError: unknown operator: $gtt

何が起きているか:$gt(より大きい)を $gtt と書き間違えたため、MongoDB のサーバーが知らない演算子として断りました。$ で始まる名前は演算子として扱われます。

直し方:$gt・$gte・$lt・$lte・$ne・$in のように、正しい綴りの演算子を使います。

パイプラインのステージ名を間違えた

エラーになるコード

db.products.aggregate([{ $groupp: { _id: '$category' } }])

画面に出るメッセージ(抜粋)

MongoServerError: Unrecognized pipeline stage name: '$groupp'

何が起きているか:aggregate の配列に並べた $groupp が、MongoDB の知っているステージ名ではなかったためです。

直し方:$match・$group・$sort・$project・$lookup のように、正しいステージ名に直します。

メソッド名を間違えた

エラーになるコード

db.products.fnd({ price: 150 })

画面に出るメッセージ(抜粋)

TypeError: db.products.fnd is not a function

何が起きているか:find を fnd と書き間違えたためです。mongosh では db.products のあとに続く名前が JavaScript のメソッドとして呼ばれるので、存在しない名前だとサーバーに送る前に JavaScript のエラーになります。

直し方:メソッド名の綴りを見直します。mongosh では途中まで打って Tab キーを押すと候補が表示されます。

ほかのデータベースの解説

  • PostgreSQL 1986年にカリフォルニア大学バークレー校で始まった研究プロジェクト POSTGRES が元で・リレーショナルデータベース
  • MySQL 1995年・リレーショナルデータベース
  • DuckDB 2019年・組み込み型の分析用
  • Redis 2009年・インメモリのキーバリューストア

5つのデータベースと SQLite を並べた比較は データベースを整える にあります。 書いたコードはどこにも送られません(このページに入力欄はクイズの選択だけで、選んだ答えも記録しません)。

このツールについて

データを表の行ではなく JSON に似た「ドキュメント」として保存するデータベースで、Web やアプリのバックエンドでよく使われています。

MongoDB の概要と、同じ6つのお題をドキュメントの書き方で。find・aggregate・$lookup の動きを再現した練習場つき。

主な機能

  • 概要(誕生・作った人・種類・ライセンス)と日本での使われ方・クラウドサービス・研修と資格
  • 同じ商品と注文のデータで6つのお題(PostgreSQL・MySQL・DuckDB・Redis の同じお題へ移れる)
  • 出力当てクイズ4問(正解と理由)
  • よくあるエラー4件(実際のメッセージ・原因・直し方)
  • find・aggregate・updateOne(upsert)などの動きを再現した練習場(本物ではない)
  • 表示は mongosh に寄せた形・送信ゼロ

よくある質問

Q. 練習場では本物の MongoDB が動いているのですか?

A. 動いていません。MongoDB はブラウザの中で動かせないため、find の条件や aggregate のパイプラインを、MongoDB の問い合わせ言語の JavaScript 実装である mingo で再現しています。表示は mongosh に寄せた形で、フィールドの並びや数値の型などの細部は本物と違うことがあります。

Q. このページの結果は本物の MongoDB で確かめたものですか?

A. いいえ。この環境では MongoDB 本体を動かせなかったため、表示している結果は練習場の再現の出力です。ほかのデータベースのページ(本物で照合)とは確かめ方が違うことを、ページにも書いています。

Q. MongoDB に JOIN はありますか?

A. aggregate の $lookup で、別のコレクションの文書を結びつけられます。ただ、MongoDB では関係の深いデータを1つの文書の中に入れておく(埋め込む)設計がよく使われ、$lookup はそれでは足りないときに使います。

入力値はURLの「#」以降に入るためサーバーには送信されません。リンクを開くと同じ状態を復元します。

続けて整える

運営サイト

私たちが運営するサイト