php - Elasticsearch 短语/多世界搜索
问题描述
我正在尝试实现一个用例,其中用户可以对“product_name”字段进行多词/短语搜索。
假设有人在搜索“最富有的人”,应该会出现以下结果:
- 巴比伦首富
- 首富的故事
- 世界上最富有的人
- 如何赢得首富
搜索结果不得包含以下文档 -
- 最富有的女人和男人
- 当一个穷人成为最富有的人
这是我写的分析器:
'settings' => [
'analysis' => [
'filter' => [
'autocomplete_filter' => ['type' => 'ngram', 'min_gram' => 1, 'max_gram' => 10]
],
'analyzer' => [
'autocomplete' => ['type' => 'custom', 'tokenizer' => 'standard', 'filter' => ['lowercase', 'autocomplete_filter']]
]
],
'index.max_ngram_diff' => 10
],
'mappings' => ['properties' => [
'product_name' => ['type' => 'text', 'analyzer' => 'autocomplete', 'search_analyzer', 'standard'],
]],
我正在使用以下用 PHP 编写的代码来发出搜索请求:
$params = [
'index' => ProductData::ELASTIC_INDEX,
'type' => ProductData::ELASTIC_TYPE,
'body' => [
'query' => ['match' => ['product_name' => ['query' => $requestVars['product_name']]]
],
]
];
$result = $this->client->search($params);
但是,我得到的结果是出乎意料的,而不是我上面列出的结果。
解决方案
由于您已经定义了autocomplete
分析器,其中有一个 n-gram 标记器,因此生成的标记"When a poor man becomes the richest"
将包括"when"
, "a"
, "poor"
, "man"
, "becomes"
, "the"
, "richest"
。
现在,当您搜索 时,这将返回所有在其文档中具有或Richest Man
的匹配文档richest
man
您可以简单地使用match_phrase 查询,而不是定义任何单独的分析器
添加一个工作示例
索引映射:
{
"mappings": {
"properties": {
"name": {
"type": "text"
}
}
}
}
搜索查询:
{
"query": {
"match_phrase": {
"name": "Richest Man"
}
}
}
搜索结果将是
"hits": [
{
"_index": "67784465",
"_type": "_doc",
"_id": "1",
"_score": 0.15394104,
"_source": {
"name": "The Richest Man in Babylon"
}
},
{
"_index": "67784465",
"_type": "_doc",
"_id": "2",
"_score": 0.15394104,
"_source": {
"name": "Story of the Richest man"
}
},
{
"_index": "67784465",
"_type": "_doc",
"_id": "3",
"_score": 0.14290144,
"_source": {
"name": "The richest man in the world"
}
},
{
"_index": "67784465",
"_type": "_doc",
"_id": "4",
"_score": 0.14290144,
"_source": {
"name": "How to win the richest man"
}
}
]
推荐阅读
- ruby-on-rails - 无法确定在 Digitalocean 上为我的 rails 应用程序安装 yarn add dropzone 的位置
- android - 如何在 Kotlin 中将数据从 Service 传递到 Activity?
- java - 卡在 Project Euler 的问题 3 上,即找到给定数字的最大素数。请查看详情
- android - Android 检测堆转储捕获
- php - 仅允许活动用户登录
- mongodb - 如何根据 Mongo 中的现有值更新对象数组中的属性?
- c - 如何将 C 中变量的值传递给内联汇编中指令的参数?
- arrays - 未定义的数组?TypeError:无法读取未定义的属性“地图”
- design-patterns - 火花流设计模式
- php - 需要从数据库获取信息并显示的建议