MongoDB supporta le espressioni regolari utilizzando l'operatore $regex. Tuttavia, queste query MongoDB regex hanno uno svantaggio, tutti i tipi di espressione regolare tranne uno fanno un uso scarso degli indici e provocano problemi di prestazioni. Per un server di produzione con grandi quantità di dati, una query regex errata può mettere in ginocchio il tuo server.
Le query basate su espressioni regolari MongoDB sono una query abbastanza comune nella maggior parte delle applicazioni che utilizzano MongoDB. È simile all'operazione "MI PIACE" supportata sulla maggior parte dei database relazionali. La sintassi del comando è la seguente
{ $regex: /pattern/, $options: '<options>' } E.g. { name: { $regex: /^acme.*test/}}
Per informazioni più dettagliate sull'operazione regex e opzioni aggiuntive, fare riferimento alla documentazione di MongoDB
Per il resto di questa discussione, assumeremo che il campo che stai confrontando abbia un indice. Se non si indicizza, si verificherà una scansione della raccolta e prestazioni molto scarse. Tuttavia, anche se il campo è indicizzato, le prestazioni possono risultare scadenti. Il motivo è che MongoDB può fare un buon uso degli indici solo se la tua espressione regolare è una "espressione prefissata":si tratta di espressioni che iniziano con il carattere "^".
Per esempio. { nome: { $regex: /^acme/}}
Ciò consente a MongoDB di identificare un intervallo di voci di indice che sono rilevanti per questa query e si traduce in query efficienti. Qualsiasi altra query risulta in una scansione dell'indice poiché MongoDB non è in grado di restringere la scansione a un intervallo di voci di indice. Una scansione dell'indice è particolarmente negativa poiché tutti gli indici devono essere impaginati in memoria e ciò influisce sul set di lavoro del server (in effetti la scansione dell'indice potrebbe portare a prestazioni peggiori rispetto a una scansione della raccolta:provoca il doppio del numero di errori di pagina ).
Diamo un'occhiata ad alcuni esempi e ai piani di query risultanti. Per i nostri scopi di test ho impostato una raccolta con 100.000 documenti. Ogni documento ha un campo firstName che è una stringa di 16 caratteri.
Esempio 1: { nome:{ $regex:/^acme/}}
Risultato:utilizzo efficiente dell'indice
Piano di query:
executionStats" : { "executionSuccess" : true, "nReturned" : 0, "executionTimeMillis" : 0, "totalKeysExamined" : 1, "totalDocsExamined" : 0,
Esempio 2: { nome:{ $regex:/^acme/i}}
Risultato:scansione dell'indice inefficiente a causa del requisito senza distinzione tra maiuscole e minuscole. Quindi, in pratica, l'opzione /i nega l'"espressione del prefisso"
Piano di query:
"executionStats" : { "executionSuccess" : true, "nReturned" : 0, "executionTimeMillis" : 137, "totalKeysExamined" : 100000, "totalDocsExamined" : 0,
Esempio 3: { nome:{ $regex:/acme.*corp/}}
Risultato:scansione dell'indice inefficiente
Piano di query:
"executionSuccess" : true, "nReturned" : 0, "executionTimeMillis" : 167, "totalKeysExamined" : 100000, "totalDocsExamined" : 0,
Esempio 4: { nome:{ $regex:/acme/}}
Risultato:scansione dell'indice inefficiente
"executionStats" : { "executionSuccess" : true, "nReturned" : 0, "executionTimeMillis" : 130, "totalKeysExamined" : 100000, "totalDocsExamined" : 0,