Ich habe vor kurzem angefangen, ElasticSearch zu verwenden, und ich kann es scheinbar nicht schaffen, nach einem Teil eines Wortes zu suchen.
Beispiel: Ich habe drei Dokumente aus meiner Couchdb in ElasticSearch indiziert:
{
"_id" : "1",
"name" : "John Doeman",
"function" : "Janitor"
}
{
"_id" : "2",
"name" : "Jane Doewoman",
"function" : "Teacher"
}
{
"_id" : "3",
"name" : "Jimmy Jackal",
"function" : "Student"
}
Jetzt möchte ich nach allen Dokumenten suchen, die "Doe" enthalten.
curl http://localhost:9200/my_idx/my_type/_search?q=Doe
Das gibt keine Treffer zurück. Aber wenn ich suche
curl http://localhost:9200/my_idx/my_type/_search?q=Doeman
Es wird ein Dokument zurückgegeben (John Doeman).
Ich habe versucht, verschiedene Analysatoren und verschiedene Filter als Eigenschaften meines Index festzulegen. Ich habe auch versucht, eine vollständige Abfrage zu verwenden (zum Beispiel:
{
"query": {
"term": {
"name": "Doe"
}
}
}
) Aber nichts scheint zu funktionieren.
Wie kann ich ElasticSearch dazu bringen, sowohl John Doeman als auch Jane Doewoman zu finden, wenn ich nach "Doe" suche?
AKTUALISIEREN
Ich habe versucht, den nGram-Tokenizer und -Filter wie von Igor vorgeschlagen zu verwenden:
{
"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
}
}
}
}
}
Das Problem, das ich jetzt habe, ist, dass jede einzelne Abfrage ALLE Dokumente zurückgibt. Irgendwelche Hinweise? Die ElasticSearch-Dokumentation zur Verwendung von nGram ist nicht großartig ...
quelle
Antworten:
Ich benutze auch nGram. Ich benutze Standard Tokenizer und nGram nur als Filter. Hier ist mein Setup:
Lassen Sie uns Wortteile mit bis zu 50 Buchstaben finden. Passen Sie das max_gram nach Bedarf an. In deutscher Sprache kann es sehr groß werden, deshalb habe ich einen hohen Wert festgelegt.
quelle
Die Suche mit führenden und nachfolgenden Platzhaltern wird in einem großen Index extrem langsam sein. Wenn Sie nach dem Wortpräfix suchen möchten, entfernen Sie den führenden Platzhalter. Wenn Sie wirklich einen Teilstring in der Mitte eines Wortes finden müssen, sollten Sie den ngram-Tokenizer verwenden.
quelle
Ich denke, es ist nicht nötig, ein Mapping zu ändern. Versuchen Sie, query_string zu verwenden , es ist perfekt. Alle Szenarien funktionieren mit dem Standard-Standardanalysator:
Wir haben Daten:
Szenario 1:
Antwort:
Szenario 2:
Antwort:
Szenario 3:
Antwort:
BEARBEITEN - Gleiche Implementierung mit elastischer Suche nach Federdaten https://stackoverflow.com/a/43579948/2357869
Eine weitere Erklärung, wie query_string besser ist als andere https://stackoverflow.com/a/43321606/2357869
quelle
Ohne Ihre Indexzuordnungen zu ändern, können Sie eine einfache Präfixabfrage durchführen, die Teilsuchen durchführt, wie Sie es sich erhoffen
dh.
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-prefix-query.html
quelle
Probieren Sie die Lösung aus, die hier beschrieben wird: Genaue Teilstringsuche in ElasticSearch
Zur Lösung des Problems der Datenträgernutzung und des Problems mit zu langen Suchbegriffen werden kurze, 8 Zeichen lange ngramme verwendet (konfiguriert mit: "max_gram": 8 ). Um nach Begriffen mit mehr als 8 Zeichen zu suchen, verwandeln Sie Ihre Suche in eine boolesche UND-Abfrage, die nach jeder einzelnen 8-stelligen Teilzeichenfolge in dieser Zeichenfolge sucht. Wenn ein Benutzer beispielsweise nach einem großen Yard (einer 10-stelligen Zeichenfolge) sucht, lautet die Suche wie folgt:
"Arge ya und Arge yar und Rge Yard .
quelle
min_gram
undmax_gram
es scheint, als würde er linear von der Größe der Feldwerte und dem Bereich vonmin
und abhängenmax
. Wie verpönt ist es, so etwas zu benutzen?ngram
es sich um einen Filter über einem Tokenizer handelt? Könnten Sie es nicht einfach als Tokenizer verwenden und dann einen Kleinbuchstabenfilter anwenden?index_ngram: { type: "custom", tokenizer: "ngram_tokenizer", filter: [ "lowercase" ] }
Ich habe es versucht und es scheint die gleichen Ergebnisse mit der Analysetest-APIWenn Sie die Autocomplete-Funktionalität implementieren möchten, ist Completion Suggester die beste Lösung. Der nächste Blog-Beitrag enthält eine sehr klare Beschreibung, wie dies funktioniert.
Mit zwei Worten, es handelt sich um eine speicherinterne Datenstruktur namens FST, die gültige Vorschläge enthält und für schnelles Abrufen und Speichernutzung optimiert ist. Im Wesentlichen ist es nur eine Grafik. Zum Beispiel, und FST , die die Worte
hotel
,marriot
,mercure
,munchen
undmunich
würde wie folgt aussehen:quelle
Sie können Regexp verwenden.
Wenn Sie diese Abfrage verwenden:
Sie erhalten alle Daten, deren Name mit "J" beginnt. Wenn Sie nur die ersten beiden Datensätze erhalten möchten, deren Name mit "man" endet, können Sie diese Abfrage verwenden:
und wenn Sie alle Datensätze erhalten möchten, deren Name "m" enthält, können Sie diese Abfrage verwenden:
Das funktioniert bei mir. Und ich hoffe, meine Antwort ist geeignet, um Ihr Problem zu lösen.
quelle
Die Verwendung von Wilcards (*) verhindert die Berechnung einer Punktzahl
quelle
Ich benutze das und habe mich arbeiten lassen
quelle
Keine Ursache.
Ich musste mir die Lucene-Dokumentation ansehen. Scheint, ich kann Platzhalter verwenden! :-)
macht den Trick!
quelle