2016-07-05 14 views
15

Używam MongoDB i mam zbiór dokumentów o następującej strukturze:Index Bounds na Mongo Regex Szukaj

{ 
    fName:"Foo", 
    lName:"Barius", 
    email:"[email protected]", 
    search:"foo barius" 
} 

buduję funkcję, która będzie wykonywać zwykłe wyszukiwanie słowa w polu search . Aby zoptymalizować wydajność, zaindeksowałem tę kolekcję w polu wyszukiwania. Jednak sprawy wciąż są nieco powolne. Więc prowadził explain() na kwerendzie próbki:

db.Collection.find({search:/bar/}).explain(); 

patrząc pod zwycięskiego planu, widzę stosować następujące granice Index:

"search": [ 
     "[\"\", {})", 
     "[/.*bar.*/, /.*bar.*/]" 
] 

Drugi zestaw ma sens - to patrząc od wszystkiego, co zawiera pasek do wszystkiego, co zawiera pasek. Jednak pierwszy zestaw mnie oszałamia. Wygląda na to, że patrzy się w zakresie od "" włącznie do {} wyłącznie. Obawiam się, że ten dodatkowy zestaw ograniczeń spowalnia moje zapytanie. Czy to konieczne, aby zachować? Jeśli nie, jak mogę zapobiec dołączeniu go?

+0

Czy ten sam problem, znalazłeś wyjaśnienie? – kirhgoff

+0

@kirhgoff Którą wersję mongoDB używasz? – barbakini

+0

@kirhgoff co używasz 'mongoDB native' lub' mongoose'. Sprawdź to - http://voidcanvas.com/mongoose-vs-mongodb-native/ –

Odpowiedz

5

Myślę, że to po prostu sposób, w jaki mongodb działa z regex (patrz https://scalegrid.io/blog/mongodb-regular-expressions-indexes-performance/). Po prostu uważaj na wartość nscanned/totalKeysExamined, jeśli jest zbyt duża, to indeks jest bezużyteczny dla twojego zapytania.

Zobacz także: MongoDB, performance of query by regular expression on indexed fields

+0

Zgadzam się, jak stwierdzono w dokumentacji MongoDB oraz w https://stackoverflow.com/a/33219393/8291949 jeśli twoje wyrażenie nie jest "wyrażeniem prefiksowym", mongo przeszuka klucze w indeksie, wtedy pobierze dopasowane dokumenty (które powinny być jeszcze szybsze niż pełne skanowanie kolekcji). – wp78de

0

ten sposób Mongo współpracuje z tego typu regex oraz indeks. Mam na myśli to, że szukasz/bar/zamiast/^ bar /.

Po określeniu indeksu w tym polu następuje indeksowanie od pierwszego znaku. Tak więc "Foo Barius" jest indeksowane zaczynając od F. Ponieważ wyszukujesz "pasek" w dowolnym miejscu na polu, musisz przeszukać cały indeks tego pola patrząc * pasek *.

Pierwsza linijka w opisie wyjaśnia, jak wygląda każdy rekord w indeksie.

Druga linia mówi, daj mi tylko te wskaźniki z (1), które mają w sobie pręt.

Podsumowanie: Zaprojektuj swoje rekordy, aby efektywnie korzystać z indeksu. W przypadku ciągów upewnij się, że twoje wyszukiwania znajdują się na początku łańcucha, np./^ Bar /. Jeśli zamierzam wyszukiwać według nazwiska, musi najpierw wystąpić w indeksowanym polu.

Jako ćwiczenie wykonaj wyjaśnienie na/^ bar/zamiast. Nie dostaniesz danych, ale pierwsze ograniczenia indeksu będą miały postać/^ bar/to/^ bas /.

Mam nadzieję, że moja odpowiedź na strumień świadomości jest pomocna.

UDude

-1

Myślałem, że dodam moje dwa centy.

Poprzednie dwie odpowiedzi są prawidłowe. Wyrażenie regex może korzystać tylko ze standardowego indeksu, jeśli zaczniesz wyszukiwanie od początku. W rzeczywistości posiadanie indeksu i wyszukiwanie przez regex może mieć szkodliwy wpływ na twoje wyszukiwanie, ponieważ próbuje użyć indeksu, ale nie odniesie sukcesu.

Istnieje inny rodzaj indeksu, który może być przydatny w twojej sytuacji. Indeks tekstowy Mongo.It indeksy każde słowo w oparciu o przestrzeniach, więc byłoby w stanie zrobić indeksowany przeszukiwanie zarówno słowa „foo” i „barius”, co może być bardziej wykorzystywać

Oto docs dla że: https://docs.mongodb.com/manual/core/index-text/