MongoDB podporuje regulární výrazy pomocí operátoru $regex. Tyto dotazy na regulární výraz MongoDB však mají nevýhodu, všechny až na jeden typ regulárních výrazů špatně využívají indexy a vedou k problémům s výkonem. U produkčního serveru s velkým množstvím dat může špatný dotaz na regulární výraz srazit váš server na kolena.
Dotazy založené na regulárních výrazech MongoDB jsou poměrně běžným dotazem ve většině aplikací používajících MongoDB. To je podobné operaci „LIKE“ podporované ve většině relačních databází. Syntaxe příkazu je následující
{ $regex: /pattern/, $options: '<options>' } E.g. { name: { $regex: /^acme.*test/}}
Podrobnější informace o operaci regulárních výrazů a dalších možnostech naleznete v dokumentaci MongoDB
Pro zbytek této diskuse budeme předpokládat, že pole, se kterým se shodujete, má index. Pokud neindexujete, bude to mít za následek skenování kolekce a velmi slabý výkon. I když je pole indexováno, může to mít za následek špatný výkon. Důvodem je, že MongoDB může dobře využívat indexy pouze v případě, že váš regulární výraz je „prefixový výraz“ – jedná se o výrazy začínající znakem „^“.
Např. { name: { $regex: /^acme/}}
To umožňuje MongoDB identifikovat rozsah položek indexu, které jsou relevantní pro tento dotaz, a výsledkem jsou efektivní dotazy. Jakýkoli jiný dotaz vede ke skenování indexu, protože MongoDB není schopen zúžit skenování na rozsah položek indexu. Skenování indexu je obzvláště špatné, protože všechny indexy je třeba stránkovat do paměti, což ovlivňuje pracovní sadu vašeho serveru (ve skutečnosti může skenování indexu vést k horšímu výkonu než skenování kolekce – má za následek dvojnásobný počet chyb stránky ).
Podívejme se na některé příklady a výsledné plány dotazů. Pro naše testovací účely jsem nastavil sbírku se 100 000 dokumenty. Každý dokument má pole FirstName, což je řetězec 16 znaků.
Příklad 1: { name:{ $regex:/^acme/}}
Výsledek:Efektivní využití indexu
Plán dotazů:
executionStats" : { "executionSuccess" : true, "nReturned" : 0, "executionTimeMillis" : 0, "totalKeysExamined" : 1, "totalDocsExamined" : 0,
Příklad 2: { name:{ $regex:/^acme/i}}
Výsledek:Neefektivní skenování indexu kvůli požadavku bez rozlišení velikosti písmen. Možnost /i tedy v podstatě neguje „výraz předpony“
Plán dotazu:
"executionStats" : { "executionSuccess" : true, "nReturned" : 0, "executionTimeMillis" : 137, "totalKeysExamined" : 100000, "totalDocsExamined" : 0,
Příklad 3: { name:{ $regex:/acme.*corp/}}
Výsledek:Neefektivní skenování indexu
Plán dotazů:
"executionSuccess" : true, "nReturned" : 0, "executionTimeMillis" : 167, "totalKeysExamined" : 100000, "totalDocsExamined" : 0,
Příklad 4: { name:{ $regex:/acme/}}
Výsledek:Neefektivní skenování indexu
"executionStats" : { "executionSuccess" : true, "nReturned" : 0, "executionTimeMillis" : 130, "totalKeysExamined" : 100000, "totalDocsExamined" : 0,