Niedawno zacząłem używać ElasticSearch i nie mogę zmusić go do wyszukania części słowa.
Przykład: Mam trzy dokumenty z mojej couchdb zindeksowane w ElasticSearch:
{
"_id" : "1",
"name" : "John Doeman",
"function" : "Janitor"
}
{
"_id" : "2",
"name" : "Jane Doewoman",
"function" : "Teacher"
}
{
"_id" : "3",
"name" : "Jimmy Jackal",
"function" : "Student"
}
Więc teraz chcę wyszukać wszystkie dokumenty zawierające „Doe”
curl http://localhost:9200/my_idx/my_type/_search?q=Doe
To nie zwraca żadnych trafień. Ale jeśli szukam
curl http://localhost:9200/my_idx/my_type/_search?q=Doeman
Zwraca jeden dokument (John Doeman).
Próbowałem ustawić różne analizatory i różne filtry jako właściwości mojego indeksu. Próbowałem również użyć pełnego zapytania (na przykład:
{
"query": {
"term": {
"name": "Doe"
}
}
}
) Ale wydaje się, że nic nie działa.
Jak sprawić, by ElasticSearch wyszukał zarówno John Doeman, jak i Jane Doewoman, gdy wyszukuję „Doe”?
AKTUALIZACJA
Próbowałem użyć tokenizera i filtra nGram, jak zaproponował Igor, w ten sposób:
{
"index": {
"index": "my_idx",
"type": "my_type",
"bulk_size": "100",
"bulk_timeout": "10ms",
"analysis": {
"analyzer": {
"my_analyzer": {
"type": "custom",
"tokenizer": "my_ngram_tokenizer",
"filter": [
"my_ngram_filter"
]
}
},
"filter": {
"my_ngram_filter": {
"type": "nGram",
"min_gram": 1,
"max_gram": 1
}
},
"tokenizer": {
"my_ngram_tokenizer": {
"type": "nGram",
"min_gram": 1,
"max_gram": 1
}
}
}
}
}
Problem, który mam teraz, polega na tym, że każde zapytanie zwraca WSZYSTKIE dokumenty. Jakieś wskazówki? Dokumentacja ElasticSearch dotycząca korzystania z nGram nie jest świetna ...
źródło
Odpowiedzi:
Ja też używam nGram. Używam standardowego tokenizera i nGram tylko jako filtra. Oto moja konfiguracja:
Znajdźmy części słów do 50 liter. Dostosuj max_gram według potrzeb. Po niemiecku może być naprawdę duży, więc ustawiłem go na wysoką wartość.
źródło
Wyszukiwanie za pomocą wiodących i końcowych symboli wieloznacznych będzie bardzo powolne w przypadku dużego indeksu. Jeśli chcesz mieć możliwość wyszukiwania według prefiksu słowa, usuń wiodący symbol wieloznaczny. Jeśli naprawdę potrzebujesz znaleźć podciąg w środku słowa, lepiej byłoby użyć tokenizera ngram.
źródło
Myślę, że nie ma potrzeby zmieniać żadnego mapowania. Spróbuj użyć query_string , jest doskonały. Wszystkie scenariusze będą działać z domyślnym standardowym analizatorem:
Posiadamy dane:
Scenariusz 1:
Odpowiedź:
Scenariusz 2:
Odpowiedź:
Scenariusz 3:
Odpowiedź:
EDYCJA - ta sama implementacja z elastycznym wyszukiwaniem danych sprężynowych https://stackoverflow.com/a/43579948/2357869
Jeszcze jedno wyjaśnienie, w jaki sposób query_string jest lepszy niż inne https://stackoverflow.com/a/43321606/2357869
źródło
bez zmiany mapowania indeksu możesz wykonać proste zapytanie przedrostkowe, które będzie wykonywać częściowe wyszukiwania, na które masz nadzieję
to znaczy.
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-prefix-query.html
źródło
Wypróbuj rozwiązanie za pomocą opisanego tutaj: Dokładne wyszukiwanie podłańcuchów w ElasticSearch
Aby rozwiązać problem użycia dysku i problem ze zbyt długim terminem wyszukiwania, używane są krótkie 8-znakowe ngramy (skonfigurowane z: "max_gram": 8 ). Aby wyszukać terminy zawierające więcej niż 8 znaków, zamień swoje wyszukiwanie na zapytanie logiczne ORAZ wyszukujące każdy odrębny 8-znakowy podciąg w tym ciągu. Na przykład, jeśli użytkownik szukał dużego podwórka (10-znakowy ciąg), wyszukiwanie wyglądałoby tak:
„arge ya AND arge yar AND rge yard .
źródło
min_gram
imax_gram
wydaje się, że będzie to zależne liniowo od rozmiaru wartości pól i zakresumin
imax
. Jak niezadowolony jest z używania czegoś takiego?ngram
jest to filtr ponad tokenizerem? czy nie mógłbyś po prostu mieć go jako tokenizera, a następnie zastosować filtr z małych liter ...index_ngram: { type: "custom", tokenizer: "ngram_tokenizer", filter: [ "lowercase" ] }
Próbowałem i wydaje się, że daje te same wyniki przy użyciu interfejsu testowego analizatoraJeśli chcesz zaimplementować funkcję autouzupełniania, sugestia ukończenia jest najbardziej zgrabnym rozwiązaniem. Następny wpis na blogu zawiera bardzo jasny opis, jak to działa.
Krótko mówiąc, jest to struktura danych w pamięci zwana FST, która zawiera ważne sugestie i jest zoptymalizowana pod kątem szybkiego pobierania i wykorzystania pamięci. Zasadniczo jest to tylko wykres. Na przykład, i FST zawierającego słowa
hotel
,marriot
,mercure
,munchen
imunich
będzie wyglądać następująco:źródło
możesz użyć wyrażenia regularnego.
jeśli używasz tego zapytania:
podasz wszystkie dane, których nazwa zaczyna się na literę „J”. Zastanów się, czy chcesz otrzymać tylko pierwsze dwa rekordy, które kończą się na „man”, więc możesz użyć tego zapytania:
a jeśli chcesz otrzymać wszystkie rekordy, które w ich imieniu istnieją „m”, możesz użyć tego zapytania:
To działa dla mnie. Mam nadzieję, że moja odpowiedź będzie odpowiednia do rozwiązania twojego problemu.
źródło
Używanie wilcards (*) zapobiega obliczaniu wyniku
źródło
Używam tego i udało mi się
źródło
Nieważne.
Musiałem zajrzeć do dokumentacji Lucene. Wygląda na to, że mogę używać symboli wieloznacznych! :-)
Zrób sztuczkę!
źródło