MongoDB поддържа регулярни изрази с помощта на оператора $regex. Въпреки това тези заявки за регулярни изрази в MongoDB имат недостатък, всички освен един тип регулярни изрази използват лошо индексите и водят до проблеми с производителността. За производствен сървър с големи количества данни, лошата заявка за регулярни изрази може да постави сървъра ви на колене.
Заявките, базирани на MongoDB, са доста често срещана заявка в повечето приложения, използващи MongoDB. Това е подобно на операцията „LIKE“, поддържана в повечето релационни бази данни. Синтаксисът на командата е както следва
{ $regex: /pattern/, $options: '<options>' } E.g. { name: { $regex: /^acme.*test/}}
За по-подробна информация относно операцията с регулярни изрази и допълнителни опции вижте документацията на MongoDB
За останалата част от тази дискусия ще приемем, че полето, с което съпоставяте, има индекс. Ако не индексирате, това ще доведе до сканиране на колекция и много лошо представяне. Въпреки това, дори ако полето е индексирано, това може да доведе до лоша производителност. Причината е, че MongoDB може да използва добре индексите само ако вашият регулярен израз е „префиксен израз“ – това са изрази, започващи със знака „^“.
напр. { име: { $regex: /^acme/}
Това позволява на MongoDB да идентифицира диапазон от записи в индекса, които са от значение за тази заявка, и води до ефективни заявки. Всяка друга заявка води до сканиране на индекс, тъй като MongoDB не може да стесни сканирането до диапазон от записи в индекса. Сканирането на индекса е особено лошо, тъй като всички индекси трябва да бъдат страници в паметта и това се отразява на работния набор на вашия сървър (Всъщност сканирането на индекса може да доведе до по-лоша производителност от сканирането на колекция - води до два пъти по-голям брой грешки в страницата ).
Нека разгледаме някои примери и получените планове за заявка. За целите ни на тестване настроих колекция със 100 000 документи. Всеки документ има поле firstName, което е низ от 16 символа.
Пример 1: { име:{ $regex:/^acme/}
Резултат:Ефективно използване на индекса
План на заявката:
executionStats" : { "executionSuccess" : true, "nReturned" : 0, "executionTimeMillis" : 0, "totalKeysExamined" : 1, "totalDocsExamined" : 0,
Пример 2: { име:{ $regex:/^acme/i}}
Резултат:Неефективно сканиране на индекса поради изискване за независимо от главните букви. Така че по принцип опцията /i отрича „префиксния израз“
План на заявката:
"executionStats" : { "executionSuccess" : true, "nReturned" : 0, "executionTimeMillis" : 137, "totalKeysExamined" : 100000, "totalDocsExamined" : 0,
Пример 3: { име:{ $regex:/acme.*corp/}
Резултат:Неефективно сканиране на индекса
План на заявката:
"executionSuccess" : true, "nReturned" : 0, "executionTimeMillis" : 167, "totalKeysExamined" : 100000, "totalDocsExamined" : 0,
Пример 4: { име:{ $regex:/acme/}}
Резултат:Неефективно сканиране на индекс
"executionStats" : { "executionSuccess" : true, "nReturned" : 0, "executionTimeMillis" : 130, "totalKeysExamined" : 100000, "totalDocsExamined" : 0,