スキーマは消えたのではなく場所を移した
一言でいうと
ドキュメントデータベースは「スキーマのないデータベース」ではなく、スキーマをアプリケーションが持っているデータベースです。スキーマがなくなったのではなく、置き場所が移っただけです。
なぜ必要なのか: 「柔軟」を読み違えると
MongoDBを初めて使うとき、最もよくある期待は「カラムを事前に決めなくてよいので、素早く作れる」というものです。そのとおりですが、その代償がどこへ行ったのかは見えにくいものです。
RDBではqtyに文字列を入れると、その場で拒否されます。ドキュメントDBでは入ってしまいます。そして数か月後に集計クエリがおかしな値を返したときに、初めて気づきます。そのときには、どのドキュメントがいつから間違っていたのか、もうわかりません。
そのため、実務で使われるドキュメントDBには、たいていスキーマがあります。$jsonSchemaで設定するか、アプリケーション層(Mongoose、Pydantic)で弾きます。どちらか一方は必ずあります。
では何が本当に違うのか
違いはスキーマの有無ではなく、1回の取得で何が一緒に返ってくるかです。
RDBでは注文と明細は2つのテーブルに分かれ、結合でつなげます。ドキュメントDBでは、明細を注文ドキュメントの中に埋め込めます。
{ _id: 1, customer: "김", lines: [ { name: "가방", qty: 2 }, { name: "신발", qty: 1 } ] }
注文画面が必要とするものがちょうどこの形なら、1回の取得で済みます。結合もN+1もありません。読む形のまま保存することが、ドキュメントDBの価値です。
現場では
だから、判断基準も1つに絞られます。一緒に読まれるか、別々に変わるかです。
明細がいつも注文と一緒に読まれ、注文の外で個別に更新されることがなければ、埋め込みます。逆に、商品情報のように複数の注文が同じものを指し、値が変わったらすべてに反映されなければならないなら、参照にして別に管理します。埋め込むと、その商品名を直すときに、それを抱えているドキュメントをすべて探して直さなければなりません。
「MongoDBを使ったことがあるか」を尋ねる面接で、実際に聞きたがっている答えがこれです。クエリの構文ではなく、どこまで埋め込み、どこで区切ったのかと、その理由です。