Elasticsearch corrisponde alla sottostring in php

Di seguito è riportto il mio codice per generare l'indice usando elasticsearch.Index viene generato correttamente. Fondamentalmente lo sto usando per generare autosuggest a seconda del nome del film, del nome dell'attore e del generatore.

Ora il mio requisito è che devo abbinare la sottostring con un field particolare. Funziona bene se uso $params['body']['query']['wildcard']['field'] = '*sub_word*'; . (Ad esempio, la ricerca di "a" restituisce "tom kruz", ma la ricerca di "tom kr" non restituisce alcun risultato).

Ciò corrisponde a una parola specifica in string. Voglio abbinare la sottostring contenente più parole (ad es. 'Tom kr' dovrebbe restituire 'tom kruz').

Ho trovato pochi documenti, dicendo che sarà ansible usare ' ngram '. Ma non so, come dovrei implementarlo nel mio codice, perché sto usando configurazioni basate su arrays per elasticsearch e tutti i documenti di supporto menzionano la configuration in json fromat.

Per favore aiuto.

 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); } 

Il problema qui sta nel fatto che Elasticsearch costruisce un indice invertito. Supponendo che tu usi l'analizzatore standard, la frase "tom kruz è una pistola in alto" viene divisa in 6 gettoni: tom – kruz – is – a – top – gun. Questi token vengono assegnati al documento (con alcuni metadati relativi alla posizione, ma lasciamo per ora il lato).

Se vuoi fare una partita parziale, puoi, ma solo sui token separati, non oltre il border dei token come vorresti. Il suggerimento per dividere la string di ricerca e build una query con caratteri jolly da queste stringhe è un'opzione.

Un'altra opzione potrebbe effettivamente utilizzare un filter token ngram o edge_ngram . Quello che farebbe (al momento dell'indice) sta creando quei token parziali (come t – to – tom – … – k – kr – kru – kruz – …) in anticipo e puoi semplicemente inserire 'tom kr' nella tua ricerca (corrisponde) e corrisponderebbe. Attenzione però: questo gonfierà il tuo indice (come puoi vedere, memorizzerà MOLTI più token), hai bisogno di analizzatori personalizzati e probabilmente un bel po 'di conoscenza sui tuoi mapping.

In generale, la rotta (edge_) ngram è una buona idea solo per cose come il completamento automatico, non solo per qualsiasi field di text nel tuo indice. Ci sono alcuni modi per aggirare il tuo problema, ma la maggior parte riguarda la creazione di funzionalità separate per rilevare le parole errate e provare a suggerire i termini giusti per farlo.

Prova a creare questo JSON

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

Puoi esplodere il termine di ricerca

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

E quindi creare il carattere jolly per ognuno

 foreach($searchTerms as $searchTerm) { //create the new arrays }