【MongoDB】クエリ演算子(gt・in・$regex等)の使い方

MongoDB

こんにちは、かつコーチです。

前回はCRUD操作の基本を解説し、find({ status: "active" })のような単純な一致条件での検索まで扱いました。
今回は一歩進んで、SQLの>INLIKEに相当するクエリ演算子の使い方を解説します。

MongoDBの検索条件は、$から始まるキーワードを使ってオブジェクトの形で表現するのが特徴です。
SQLの演算子と1つずつ対応させながら覚えていきましょう。

比較演算子:gt・lt・gte・lte・$ne

数値の範囲検索

SQLでWHERE age > 20のように書く比較条件は、MongoDBでは$gt(greater than)などの演算子を使います。

SQLMongoDBクエリ演算子意味
>$gtより大きい
>=$gte以上
<$ltより小さい
<=$lte以下
!=$ne等しくない
// age が 20 より大きいユーザーを検索
// SQLの WHERE age > 20 に相当
db.users.find({ age: { $gt: 20 } })

// age が 20以上30以下のユーザーを検索
// SQLの WHERE age BETWEEN 20 AND 30 に相当
db.users.find({ age: { $gte: 20, $lte: 30 } })

同じフィールドに対して複数の演算子を1つのオブジェクトにまとめて書けるのがポイントです。
$gte$lteを組み合わせることで、SQLのBETWEENと同じ範囲検索が表現できます。

配列に関する演算子:in・nin

INに相当する$in

SQLのWHERE status IN ('active', 'pending')に相当するのが$inです。
複数の候補のいずれかに一致するドキュメントを検索します。

// status が active または pending のユーザーを検索
// SQLの WHERE status IN ('active', 'pending') に相当
db.users.find({ status: { $in: ["active", "pending"] } })

// $nin は $in の否定版。SQLの NOT IN に相当
db.users.find({ status: { $nin: ["deleted", "banned"] } })

配列フィールドに対する検索

MongoDBならではの使い方として、フィールド自体が配列の場合の検索があります。
SQLでは配列型のカラムを扱うのが一般的ではないため、ここは新しい感覚が必要です。

// tags 配列に "VIP" を含むドキュメントを検索
db.users.find({ tags: "VIP" })

// tags 配列に "VIP" と "新規" の両方を含むドキュメントを検索
db.users.find({ tags: { $all: ["VIP", "新規"] } })

配列フィールドに対して単純に値を書くだけで「配列内にその値が含まれるか」を検索できる点は、SQLにはないMongoDB特有の便利さです。

パターンマッチ:$regex

LIKEに相当する正規表現検索

SQLのWHERE name LIKE '%田中%'に相当するのが$regexです。
MongoDBでは、SQLのLIKEよりも表現力の高い正規表現をそのまま条件に使えます。

// name に "田中" を含むユーザーを検索
// SQLの WHERE name LIKE '%田中%' に相当
db.users.find({ name: { $regex: "田中" } })

// 大文字・小文字を区別せず "tanaka" を含むメールアドレスを検索
db.users.find({ email: { $regex: "tanaka", $options: "i" } })

// 前方一致検索(SQLの LIKE '田中%' に相当)
db.users.find({ name: { $regex: "^田中" } })

$options: "i"を付けると、大文字・小文字を区別しない検索になります。
SQLのLIKEは基本的にワイルドカード(%_)しか使えませんが、$regexは正規表現のフル機能が使えるため、より複雑なパターンマッチが可能です。

❌よくある失敗:$regexの多用によるパフォーマンス劣化

私が実務で経験した失敗として、$regexを使った前方一致検索ではなく、部分一致検索({ $regex: "田中" }のように先頭に^を付けない書き方)を大量データに対して多用してしまい、検索が極端に遅くなったことがあります。

❌ Before:部分一致検索はインデックスを活用できず、全件スキャンになりやすい
db.users.find({ name: { $regex: "田中" } })
// データ件数が多いとレスポンスが数秒かかることも
✅ After:前方一致(^始まり)ならインデックスを活用できる
db.users.find({ name: { $regex: "^田中" } })
// nameフィールドにインデックスがあれば、範囲スキャンとして高速化される

インデックスについてはMG07で詳しく扱いますが、「部分一致検索は原則インデックスが効かない」というのはSQLのLIKE '%...%'と同じ制約です。
検索頻度の高いフィールドで自由な部分一致検索が必要な場合は、専用の全文検索エンジン(Atlas SearchやElasticsearch)の導入を検討するのが定石です。

論理演算子:and・or・$not

複数条件の組み合わせ

複数の条件をAND・ORで組み合わせたい場合は、$and$orを使います。

// age が 20以上 かつ status が active
// 実は複数条件を並べるだけで暗黙的にANDになるため、$andは省略可能なことが多い
db.users.find({ age: { $gte: 20 }, status: "active" })

// age が 20未満 または status が inactive
// SQLの WHERE age < 20 OR status = 'inactive' に相当
db.users.find({
  $or: [
    { age: { $lt: 20 } },
    { status: "inactive" }
  ]
})

複数の条件フィールドを並べるだけで暗黙のANDになる点は、初心者がつまずきやすいポイントです。
ORで組み合わせたい場合のみ、明示的に$orを使う必要があると覚えておきましょう。

まとめ

この記事のポイント

  • 比較演算子($gt$gte$lt$lte$ne)は、SQLの>BETWEENに相当する
  • $in$ninはSQLのINNOT INに相当し、配列フィールドの部分一致検索にも使える
  • $regexはSQLのLIKEよりも表現力が高いが、部分一致検索は原則インデックスが効かない
  • 複数条件を並べると暗黙的にANDになる。ORにしたい場合は$orを明示する

次に読むべき記事

検索条件の書き方が身についたところで、次回はさらに一歩進んだ「集約パイプライン(Aggregation)の基本」で、SQLのGROUP BYに相当する集計処理を解説します。

タグ: MongoDB 中級者向け 基本操作

タイトルとURLをコピーしました