下面给出的是我使用elasticsearch生成索引的代码。索引已成功生成。基本上我用它来根据电影名称、演员名称和基因生成自动建议。
现在我的要求是,我需要将子字符串与特定字段相匹配。如果我使用,这工作正常$params['body']['query']['wildcard']['field'] = '*sub_word*';
(即搜索“to”会给出“tom kruz”,但搜索“tom kr”不会返回结果)。
这仅匹配字符串中的特定单词。我想匹配包含多个单词的子字符串(即“tom kr”应该返回“tom kruz”)。
我发现很少有文档,说可以使用 'ngram'。
但我不知道,我应该如何在我的代码中实现它,因为我正在使用基于数组的 Elasticsearch 配置,并且所有支持文档都提到了 json fromat 中的配置。
请帮忙。
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);
}
这里的问题在于Elasticsearch构建了倒排索引。假设您使用标准分析器,句子“tom kruz is a topgun”将被分为 6 个标记:tom - kruz - is - a - top -gun。这些标记被分配给文档(带有一些有关该位置的元数据,但我们暂时将其放在一边)。
如果您想进行部分匹配,则可以,但只能在单独的标记上进行,而不是按照您想要的那样超出标记的边界。分割搜索字符串并从这些字符串中构建通配符查询的建议是一个选项。
另一种选择确实是使用ngram or 边_ngram令牌过滤器。这样做(在索引时)是提前创建那些部分标记(例如 t - to - tom - ... - k - kr - kru - kruz - ...),您可以输入“tom kr”在您的(匹配)搜索中,它会匹配。但要小心:这会让你的索引膨胀(如你所见,它将存储更多的令牌),你需要定制分析仪并且可能对您的映射有相当多的了解。
一般来说,(edge_)ngram 路由仅适用于自动完成等操作,而不适用于索引中的任何文本字段。有几种方法可以解决您的问题,但大多数方法都涉及构建单独的功能来检测拼写错误的单词并尝试为其建议正确的术语。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)