2016-02-05 9 views
9

Poniżej podano mój kod do generowania indeksu za pomocą elasticsearch.Index jest generowany pomyślnie. Zasadniczo używam go do generowania autosugestów w zależności od nazwy filmu, nazwy aktora i generatora.Elasticsearch dopasuj podciąg w php

Teraz moim wymaganiem jest, aby dopasować podciąg z konkretnym polem. Działa to dobrze, jeśli używam $params['body']['query']['wildcard']['field'] = '*sub_word*';. (Tzn. Szukanie "do" daje "tom kruz", ale szukanie "tom kr" nie zwraca wyniku) .

Dopasowuje tylko konkretne słowo w łańcuchu. Chcę dopasować podciąg zawierający wiele słów (tj. 'Tom kr' powinien zwrócić 'tom kruz').

Znalazłem kilku dokumentów, mówiących, że będzie to możliwe przy użyciu "ngram". Ale nie wiem, jak mam go zaimplementować w moim kodzie, ponieważ korzystam z konfiguracji opartych na tablicy dla elasticsearch, a wszystkie dokumenty wsparcia wspominają konfigurację w json fromat.

Proszę o pomoc.

require 'vendor/autoload.php'; 

$client = \Elasticsearch\ClientBuilder::create() 
->setHosts(['http://localhost:9200'])->build(); 

/*************Index a document****************/ 
$params = ['body' => []]; 
$j = 1; 
for ($i = 1; $i <= 100; $i++) { 
    $params['body'][] = [ 
     'index' => [ 
      '_index' => 'pvrmod', 
      '_type' => 'movie', 
      '_id' => $i 
     ] 
    ]; 
    if ($i % 10 == 0) 
     $j++; 
    $params['body'][] = [ 
     'title' => 'salaman khaan'.$j, 
     'desc' => 'salaman khaan description'.$j, 
     'gener' => 'movie gener'.$j, 
     'language' => 'movie language'.$j, 
     'year' => 'movie year'.$j, 
     'actor' => 'movie actor'.$j, 
    ]; 

    // Every 10 documents stop and send the bulk request 
    if ($i % 10 == 0) { 
     $responses = $client->bulk($params); 

     // erase the old bulk request 
     $params = ['body' => []]; 

     unset($responses); 
    } 
} 

// Send the last batch if it exists 
if (!empty($params['body'])) { 
    $responses = $client->bulk($params); 
} 

Odpowiedz

5

spróbować stworzyć ten JSON

{ 
"query": { 
    "filtered": { 
     "query": { 
      "bool": { 
       "should": [ 
        { 
         "wildcard": { 
          "field": { 
           "value": "tom*", 
           "boost": 1 
          } 
         } 
        }, 
        { 
         "field": { 
          "brandname": { 
           "value": "kr*", 
           "boost": 1 
          } 
         } 
        }, 
       ] 
      } 
     } 
    } 
} 

można eksplodować wyszukiwane hasło

$searchTerms = explode(' ', 'tom kruz'); 

a następnie utworzyć wieloznaczny dla każdego jeden

foreach($searchTerms as $searchTerm) { 
//create the new array 
} 
+0

Drogi costa, dziękuję za odpowiedź.Ale tylko zapytanie, czy jesteś pewien, że po uruchomieniu wyszukiwania wieloznacznego dla poszczególnych słów uzyskasz najbardziej trafne wyniki pasujące do podciągów wielostanowych? –

6

tu problem kłamstwo w tym, że Elasticsearch tworzy odwrócony indeks. Zakładając, że używasz standardowego analizatora, zdanie "tom kruz to top gun" zostaje podzielone na 6 tokenów: tom - kruz - is - a - top - gun. Te żetony zostaną przypisane do dokumentu (z pewnymi metadanymi dotyczącymi pozycji, ale na razie zostawmy to na boku).

Jeśli chcesz dokonać częściowego dopasowania, możesz, ale tylko na oddzielnych tokenach, nie przekraczać granicy żetonów, jak chcesz. Sugestia podziału ciągu wyszukiwania i budowania zapytania wieloznacznego z tych ciągów jest opcją.

Inną opcją byłoby użycie filtru tokenu ngram lub edge_ngram. To, co by to zrobiło (w czasie indeksowania) tworzy z góry te częściowe tokeny (jak t - to - tom - ... - k - kr - kru - kruz - ...) i możesz po prostu wstawić 'tom kr' w twoim (dopasowanym) wyszukiwaniu i będzie pasować. Bądź jednak ostrożny: spowoduje to powiększenie twojego indeksu (jak widać, będzie przechowywać dużo więcej tokenów), potrzebujesz custom analysers i prawdopodobnie sporo wiedzy o swoich mapowaniach.

Ogólnie rzecz biorąc, trk (edge_) ngram jest dobrym pomysłem tylko w przypadku autouzupełniania, a nie tylko w przypadku dowolnego pola tekstowego w indeksie. Istnieje kilka sposobów na obejście problemu, ale większość z nich polega na budowaniu oddzielnych funkcji wykrywających błędne słowa i próbujących zasugerować odpowiednie warunki.