2016-02-05 25 views
9

以下は、elasticsearch.Indexを使用してインデックスを生成するコードです。実際には、映画名、俳優名、および世代に応じて自動生成するために使用しています。Elasticsearchの一致部分文字列

$params['body']['query']['wildcard']['field'] = '*sub_word*';を使用すると、部分文字列を特定のフィールドと一致させる必要があります(つまり、 'to'を検索すると 'tom kruz'が表示されますが、 'tom kr' 。

これはstring内の特定の単語にのみ一致します。複数の単語を含む部分文字列に一致させたい(つまり、 'tom kr'は 'tom kruz'を返す必要があります)。

ngram」を使用して可能であると言っているドキュメントはほとんど見つかりませんでした。 しかし、私は自分のコードでどのように実装しなければならないのですか?elasticsearchの配列ベースの設定を使用しているので、すべてのサポート文書はjsonからの設定に言及しています。

助けてください。

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

答えて

5

あなたは

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

検索語を爆発そして、ここで各1

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

貴重なコスタですが、回答ありがとうございます。しかし、単なるクエリですが、個々の単語のワイルドカード検索を実行すると、複数のサブ文字列に一致する最も関連性の高い結果が得られますか? –

6

問題のためにワイルドカードを作成することができ、このJSON

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

を作成しよう嘘つき実際にElasticsearchは逆インデックスを構築しています。あなたが標準的なアナライザを使用していると仮定すると、 "tom kruzはトップガンです"という文章は6つのトークンに分割されます:tom - kruz - is - a - top - gun。これらのトークンはドキュメントに割り当てられます(そこにはいくつかのメタデータがありますが、現在はそのままにしておきます)。

部分的に一致させたい場合は、トークンの境界を越えてではなく、別々のトークンでのみ行うことができます。検索文字列を分割し、これらの文字列からワイルドカードクエリを作成することをお勧めします。

もう1つのオプションは、確かにngramまたはedge_ngramトークンフィルタを使用しています。それは(インデックス時に)それらの部分的なトークン(t - to - tom - ... - k - kr - kru - kruz - ...)を事前に作成しているだけで、あなたは 'tom kr'あなたの(マッチ)検索でそれは一致します。しかし、注意してください:これはあなたのインデックスを膨らませます(ご覧のとおり、さらに多くのトークンを格納します)。custom analysersが必要で、おそらくあなたのマッピングについての知識がかなり必要です。

一般に、(edge_)ngramルートは、オートコンプリートのようなもので、インデックス内のテキストフィールドだけでは適切ではありません。あなたの問題を回避するにはいくつかの方法がありますが、ほとんどの場合、スペルミスの単語を検出するための別個の機能を構築し、適切な用語を提案しています。

関連する問題