2014-04-23 9 views
5

Buduję funkcję autouzupełniania przy użyciu ElasticSearch. Gdy użytkownik pisze, chcę wyświetlić listę uzupełnień danych, aby użytkownik mógł wybrać jedną z nich. Na przykład, jeśli dane zawierają następujące zwroty:Wyszukiwanie prefiksu ElasticSearch - Jak uzyskać dopasowaną frazę?

very unusual 
very unlikely 
very useful 

i typy użytkowników:

very u 

chcę wyświetlić zwroty powyżej.

Używam tej kwerendy:

"query": { 
    "multi_match": { 
     "query": "very u", 
     "fields": [ 
     "name", 
     "description", 
     "contentBlocks.caption", 
     "contentBlocks.text" 
     ], 
     "type": "phrase_prefix", 
     "max_expansions": 10, 
     "cutoff_frequency": 0.001 
    } 

Dopasowuje zawartość szukam, ale wyodrębnieniu dobrane frazy w wynikach wyszukiwania jest dość niewygodne. Używałem podświetlania i kolekcjonuję dopasowane frazy, analizując najciekawsze momenty. Na przykład:

"highlight": { 
     "contentBlocks.text": [ 
     "turned the <em>very</em> <em>unusual</em> doorknob" 
     ] 
    } 

    "highlight": { 
     "contentBlocks.text": [ 
     "invented a <em>very</em> <em>useful</em> mechanism" 
     ] 
    } 

Jaki jest właściwy sposób na zrobienie tego?


„Fraza zausznika” może być w stanie robić to, co opisałem, ale to nie jest wcale oczywiste, w jaki sposób można dostać to, aby to zrobić.

mam indeksowane pola zainteresowania (na przykład, „opis”) w następujący sposób:

"description" : { 
    "index_analyzer" : "snowball_stem", 
    "search_analyzer" : "snowball_stem", 
    "type" : "string", 
    "fields" : { 
     "autocomplete" : { 
     "index_analyzer" : "shingle_analyzer", 
     "search_analyzer" : "shingle_analyzer", 
     "type" : "string" 
     } 
    } 
    }, 

Używam analizator snowball_stem dla wyszukiwania, a shingle_analyzer dla funkcji autouzupełniania. shingle_analyzer wygląda następująco:

"settings" : { 
    "analysis" : { 
     "analyzer" : { 
      "shingle_analyzer" : { 
       "type" : "custom", 
       "tokenizer" : "standard", 
       "filter" : [ 
        "standard", 
        "lowercase", 
        "shingle_filter" 
       ], 
       "char_filter" : [ 
        "html_strip" 
       ] 
      } 
     }, 
     "filter" : { 
      "shingle_filter" : { 
       "type" : "shingle", 
       "min_shingle_size" : 2, 
       "max_shingle_size" : 2 
      } 
     } 
    } 
}, 

Dokumentacja dla zausznika frazy wydaje się być całkowicie zorientowana „korekty pisowni” zamiast zakończenia. Od co ja jestem po to zakończenie, ustawić min_word_length w prądnicy i prefix_length do długości tekstu wejściowego, w tym przypadku, 2.

I spreparowanego się zapytanie sugestia na podstawie dokumentacji:

{ 
    "text" : "sa", 
    "autocomplete_description" : { 
     "phrase" : { 
      "analyzer" : "standard", 
      "field" : "description.autocomplete", 
      "size" : 10, 
      "max_errors" : 2, 
      "confidence" : 0.0, 
      "gram_size" : 2, 
      "direct_generator" : [ 
       { 
        "field" : "description.autocomplete", 
        "suggest_mode" : "always", 
        "size" : 10, 
        "min_word_length" : 2, 
        "prefix_length" : 2 
       } 
      ] 
     } 
    } 
} 

to poszukiwanie propozycje „SA” pochodzi z następującymi wynikami:

{ 
    "_shards" : { 
    "total" : 1, 
    "successful" : 1, 
    "failed" : 0 
    }, 
    "autocomplete_description" : [ { 
    "text" : "sa", 
    "offset" : 0, 
    "length" : 2, 
    "options" : [ { 
     "text" : "say", 
     "score" : 0.012580795 
    }, { 
     "text" : "sa", 
     "score" : 0.01127677 
    }, { 
     "text" : "san", 
     "score" : 0.0106529845 
    }, { 
     "text" : "sad", 
     "score" : 0.008533429 
    }, { 
     "text" : "saw", 
     "score" : 0.008107899 
    }, { 
     "text" : "sam", 
     "score" : 0.007155634 
    } ] 
    } ] 
} 

Co mogę oczekiwać, aby znaleźć dla wejścia „sa” to słowa, które zaczynają się od „SA” o dowolnej długości. Dlaczego zwraca tylko słowa składające się z dwóch lub trzech znaków? Dlaczego zwraca tylko sześć opcji? Wielowartościowe zapytanie phrase_prefix, którego używam, znajduje wiele dłuższych słów zaczynających się od "sa", takich jak "zapisywanie", "sassy", "safari" i "sałatka".

Podczas wyszukiwania sugestii dotyczących tekstu wielowyrazowego, takiego jak "jeden lub" (który występuje wiele razy w danych), nie znajduje nic. Zapytanie fraza_prefix multi_match znajduje "jeden lub więcej", "jeden lub", "jeden lub ty" i "jeden lub oba".

Jak uzyskać sugestię do zrobienia tego, co chcę?

+0

Daj mi znać, jeśli masz jakieś pytania lub mogę dodać cokolwiek do mojej odpowiedzi. –

+0

Spójrz. –

+0

Próbowałem użyć wyrażenia sugestii, aby to zrobić, ale nie odniosłem dużego sukcesu. Dodałem informacje o moich eksperymentach i bardziej szczegółowe pytania do powyższego opisu problemu. –

Odpowiedz

1

Możesz uzyskać mniej więcej to, co chcesz, dzięki completion suggester. Głównym problemem jest to, że nie jest już świadomy wyszukiwania.Możesz to naprawić, dodając suggester context, ale działa tylko w przypadku filtrów i nie uwzględnia tekstu wyszukiwania.

Jedynym sposobem, że wiem, aby uzyskać „najlepsze” zachowanie (w kontekście świadomych uzupełnienia Search), wykonaj następujące czynności:

  • Tworzenie suggestions pole, w którym tekst jest tokenized jak byś go chce być widocznym dla użytkownika (prawdopodobnie standardowy analizator lub może dodać filtr żetonów 2-gontowych).
  • Załóżmy, że użytkownik wydaje niekompletne zapytanie: very un. Za kulisami wyszukaj numer very, a następnie użyj term aggregations, aby uzyskać warunki listy, które pasują do kontekstu wyszukiwania, ale ogranicz warunki zwracane przez "include": "un.*".
  • Wynikowa lista będzie wyglądać jak [nietypowy, mało prawdopodobny, nieefektywny].

Jedyną wadą tej metody, zwłaszcza w sharded środowiska jest to, że wiele zapytań i jesteś ciągnięcie bardzo wysokie pole liczności (suggestions) do pamięci. Więc ... Nie wiem, czy to praktycznie możliwe. Więc może lepiej wrócić do sugestii ukończenia. Jeśli spróbujesz któreś z nich, chciałbym usłyszeć twoje doświadczenia z tym.

+1

Dzięki za zaglądanie do tego @JnBrymn. Skończyło się na tym, że użyłem kodu, który pierwotnie opisałem, używając zapytania phrase_prefix i przetwarzania końcowego. Wydaje się, że to hack, ale działa niezawodnie, a wydajność jest zaskakująco dobra. –

Powiązane problemy