MongoDB はクエリから始まる

Tahseen Tauseef 2023年6月20日
  1. MongoDB は、$regex を使用したクエリから始まります
  2. .改行に一致するドット文字
MongoDB はクエリから始まる

この MongoDB 記事では、ユーザーは $regex を使用してクエリを開始する方法を学習します。 クエリ内のパターン マッチング文字列の正規表現機能を提供します。

MongoDB は、$regex を使用したクエリから始まります

$regex を使用する場合は、次の構文のいずれかを使用します。

{ <field>: { $regex: /pattern/, $options: '<options>' } }
{ <field>: { $regex: 'pattern', $options: '<options>' } }
{ <field>: { $regex: /pattern/<options> } }

MongoDB では、ユーザーは正規表現オブジェクト (つまり、/pattern/) を使用して正規表現を指定することもできます。

{ <field>: /pattern/<options> }

ユーザーは、次の <options> で正規表現を使用できます。

オプション 説明 構文の制限
i 大文字と小文字を一致させるために大文字と小文字を区別しません。
m 複数行の値を持つ文字列の場合、各行の先頭または末尾で、先頭の ^ や末尾の $ などのアンカーを含むパターンに一致します。 パターンにアンカーがない場合、または文字列値に改行文字が含まれていない場合 (例: \n)、m オプションは効果がありません。
x $regex パターンのすべての空白文字は、エスケープされるか文字クラスに含まれていない限り無視されます。 また、途中の文字は無視され、エスケープされていないハッシュ/ポンド (#) 文字とそれに続く改行が含まれているため、複雑なパターンでコメントを追加できます。 空白文字は、パターン内の特殊文字シーケンス内に表示されない場合があります。 これはデータ文字にのみ関係します。 x オプションは、VT 文字 (つまり、コード 11) の処理方法には影響しません。 $options 構文で $regex が必要になります
s ドット文字 (.) は、改行を含む任意の文字と一致できます。 $options 構文で $regex が必要です

$regex 演算子は、グローバル検索修飾子 g をサポートしていません。

$in

$in クエリ式に正規表現を組み込むために使用できるのは、JavaScript 正規表現オブジェクト (つまり、/pattern/) のみです。 次の例を考えてみましょう。

{ name: { $in: [ /^acme/i, /^ack/ ] } }

$in 内では、$regex 演算子式を使用できません。

フィールドの暗黙の AND 条件

$regex 演算子を使用して、フィールドのクエリ基準のコンマ区切りリストに正規表現を組み込みます。 次の例を考えてみましょう。

{ name: { $regex: /acme.*corp/i, $nin: [ 'acmeblahcorp' ] } }
{ name: { $regex: /acme.*corp/, $options: 'i', $nin: [ 'acmeblahcorp' ] } }
{ name: { $regex: 'acme.*corp', $options: 'i', $nin: [ 'acmeblahcorp' ] } }

xs を持つ $regex 演算子

x または s オプションを使用するには、$regex 演算子を $options 演算子と共に使用する必要があります。 たとえば、i および s オプションを指定するには、$options を使用する必要があります。

{ name: { $regex: /acme.*corp/, $options: "si" } }
{ name: { $regex: 'acme.*corp', $options: "si" } }

PCRE と JavaScript

ユーザーは、JavaScript ではサポートされていない正規表現パターンで PCRE がサポートする機能を活用するために、パターンを文字列として $regex 演算子式を使用する必要があります。

たとえば、パターンで (?i)(?-i) を使用して残りのパターンの大文字と小文字を区別しないようにするには、パターンを文字列として $regex 演算子を使用する必要があります。

{ name: { $regex: '(?i)a(?-i)cme' } }

$regex$not

バージョン 4.0.7 から、$not 演算子は両方に対して論理 NOT 操作を実行できます。

  1. 正規表現オブジェクト (例: /pattern/)

    例えば:

db.inventory.find( { item: { $not: /^p.*/ } } )
  1. $regex 演算子式 (MongoDB 4.0.7 以降)。

    例えば:

db.inventory.find( { item: { $not: { $regex: "^p.*" } } } )
db.inventory.find( { item: { $not: { $regex: /^p.*/ } } } )

バージョン 4.0.6 以前では、$not 演算子を正規表現オブジェクト (例: /pattern/) で使用できましたが、$regex 演算子式では使用できませんでした。

フィールドにインデックスがある場合、MongoDB はインデックス内の値に対して正規表現をチェックします。これは、大文字と小文字を区別する正規表現クエリのコレクション スキャンよりも高速になる可能性があります。

正規表現に接頭辞式が含まれている場合、さらに最適化することができます。これは、すべての潜在的な一致が正確な文字列で始まることを示します。 これにより、MongoDB はプレフィックスから範囲を作成し、その範囲内のインデックス値とのみ照合できます。

正規表現がキャレット (^) または左アンカー (\A) で始まり、その後に単純な記号の文字列が続く場合、それはプレフィックス式と呼ばれます。 たとえば、正規表現 /^abc.*/ は、abc で始まるインデックス値に対してのみ一致することによって最適化されます。

さらに、/^a//^a.*/、および /^a.*$/ はすべて同等の文字列に一致しますが、それらのパフォーマンスは異なります。

適切なインデックスが存在する場合、これらの式はすべてそれを使用します。 それでも、/^a.*//^a.*$/ は遅いです。 プレフィックスに一致した後、/^a/ は検索を停止できます。

大文字と小文字を区別しない正規表現クエリでは、インデックスを効率的に活用できません。 たとえば、$regex 実装は照合を認識しないため、大文字と小文字を区別しないインデックスを使用できません。

例:

次の例では、次のドキュメントで products というコレクションを使用しています。

{ "_id" : 100, "ski" : "abc123", "description" : "Single line description." },
{ "_id" : 101, "ski" : "abc789", "description" : "First line\nSecond line" },
{ "_id" : 102, "ski" : "xyz456", "description" : "Many spaces before     line" },
{ "_id" : 103, "ski" : "xyz789", "description" : "Multiple\nline description" }

LIKE ステートメント

この例は、ski フィールドが "%789" のようなすべてのドキュメントに一致します。

db.products.find( { ski: { $regex: /789$/ } } )

この例は、次の SQL LIKE ステートメントに似ています。

SELECT * FROM products
WHERE ski like "%789";

大文字と小文字を区別しない正規表現一致

次の例では、i オプションを使用して、ABC で始まる ski 値を持つドキュメントに対して、大文字と小文字を区別しない一致を実行します。

db.products.find( { ski: { $regex: /^ABC/i } } )

クエリは次のドキュメントに一致します。

{ "_id" : 100, "ski" : "abc123", "description" : "Single line description." }
{ "_id" : 101, "ski" : "abc789", "description" : "First line\nSecond line" }

マルチラインマッチ

次の例では、m オプションを使用して、複数行の文字列内の文字 S で始まる行を一致させています。

db.products.find( { description: { $regex: /^S/, $options: 'm' } } )

クエリは、以下に示す次のドキュメントに一致します。

{ "_id" : 100, "ski" : "abc123", "description" : "Single line description." }
{ "_id" : 101, "ski" : "abc789", "description" : "First line\nSecond line" }

m オプションがない場合、クエリは次のドキュメントにのみ一致します。

{ "_id" : 100, "ski" : "abc123", "description" : "Single line description." }

$regex パターンにアンカーが含まれていない場合、パターンは次の例のように文字列全体に適用されます。

db.products.find( { description: { $regex: /S/ } } )

次に、$regex は両方のドキュメントに一致します。

{ "_id" : 100, "ski" : "abc123", "description" : "Single line description." }
{ "_id" : 101, "ski" : "abc789", "description" : "First line\nSecond line" }

.改行に一致するドット文字

s オプションを使用すると、ドット文字 (.) を改行を含むすべての文字に一致させることができ、i オプションを使用すると、大文字と小文字を区別しない一致が可能になります。

db.products.find( { description: { $regex: /m.*line/, $options: 'si' } } )

クエリは次のドキュメントに一致します。

{ "_id" : 102, "ski" : "xyz456", "description" : "Many spaces before     line" }
{ "_id" : 103, "ski" : "xyz789", "description" : "Multiple\nline description" }

このクエリは、s オプションを指定しないと、次のドキュメントにのみ一致します。

{ "_id" : 102, "ski" : "xyz456", "description" : "Many spaces before     line" }

パターン内の空白

一致するパターンでは、x オプションは、# で示される空白とコメントを無視し、n:. で終わります。

var pattern = "abc #category code\n123 #item number"
db.products.find( { ski: { $regex: pattern, $options: "x" } } )

クエリは次のドキュメントと一致します。

{ "_id" : 100, "ski" : "abc123", "description" : "Single line description." }