elasticsearch - 使用模糊性和 shingle 分析器使用 matchQuery 进行 Elasticsearch 搜索
问题描述
我正在使用elasticsearch并提出了这样的问题。我定义了一个带瓦类型的分析器并创建了一个映射。
这是代码:
{
"settings": {
"analysis": {
"char_filter": {
"icons": {
"type": "mapping",
"mappings_path": "analysis/char_filter.txt"
}
},
"filter": {
"synonym_filter": {
"type": "synonym",
"synonyms_path": "analysis/synonym_filter.txt"
},
"shingle_filter":{
"type":"shingle",
"max_shingle_size": 2,
"min_shingle_size": 2,
"output_unigrams": true,
"token_separator": ""
}
},
"analyzer": {
"my_analyzer": {
"filter": [
"lowercase",
"synonym_filter",
"shingle_filter"
],
"char_filter": [
"icons"
],
"tokenizer": "standard"
}
}
}
},
"mappings": {
"type-0": {
"properties": {
"text": {
"type": "text",
"analyzer": "my_analyzer"
}
}
}
}
}
然后,我将一个文档放入索引中。
{
"text":"hello"
}
在此之后,我开始像这样搜索:
{
"query":{
"match":{
"text":{
"query":"hell world",
"fuzziness":1
}
}
}
}
但它什么都不匹配。然后我将查询更改为:
{
"query":{
"match":{
"text":{
"query":"world hell",
"fuzziness":1
}
}
}
}
这个请求得到文件。
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.21576157,
"hits": [
{
"_index": "index-001",
"_type": "product",
"_id": "1",
"_score": 0.21576157,
"_source": {
"text": "hello"
}
}
]
}
}
我的弹性搜索版本是 6.2.4
谁能告诉我原因?
解决方案
fuzziness
结合shingle_filter
导致问题。如果您在匹配查询中阅读了模糊性的注释
模糊匹配不适用于具有同义词的术语或分析过程在同一位置产生多个标记的情况。 在幕后,这些术语被扩展为一个特殊的同义词查询,它混合了术语频率,它不支持模糊扩展。
注意粗体部分,同一位置的token不做模糊处理,
现在让我们检查为您的搜索词生成的令牌hell world
。
{
"tokens": [
{
"token": "hell",
"start_offset": 0,
"end_offset": 4,
"type": "<ALPHANUM>",
"position": 0 // position 0 for hell
},
{
"token": "hellworld",
"start_offset": 0,
"end_offset": 10,
"type": "shingle",
"position": 0, // again position 0 for
"positionLength": 2
},
{
"token": "world",
"start_offset": 5,
"end_offset": 10,
"type": "<ALPHANUM>",
"position": 1 //position 1
}
]
}
因此,对于位置 0 标记hell
和hellworld
模糊性将不会被应用,因此它与索引标记不匹配hello
并且不返回任何结果。
现在检查令牌world hell
{
"tokens": [
{
"token": "world",
"start_offset": 0,
"end_offset": 5,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "worldhell",
"start_offset": 0,
"end_offset": 10,
"type": "shingle",
"position": 0,
"positionLength": 2
},
{
"token": "hell",
"start_offset": 6,
"end_offset": 10,
"type": "<ALPHANUM>",
"position": 1 // this hell position is unique as 1 so it fuzziness will be applied.
}
]
}
现在,当您使用 查询时world hell
,将应用 onhell
标记fuzziness
,它将匹配hello
索引标记并返回搜索结果。
您可以再次将搜索词更改为world hell elastic
so nowhell
不会有唯一的位置,因此它不会再次带来搜索结果。希望这将清除您的概念。
推荐阅读
- json - 使用 Ruby API 呈现 json 错误:我应该使用“错误”还是“消息”键?
- sql - TSQL SET 命令在 EXEC 语句中不起作用
- python - Python - Pandas Group来自 Iterrows
- javascript - 从父构造函数调用的重写方法不会初始化字段
- node.js - 内部监视失败:ENOSPC:已达到文件监视者数量的系统限制,请观看 [heroku]
- concurrency - Serverless(如 Google Cloud Run)上的并发性是否毫无意义?
- maven - netbeans ide 中没有错误,但 java.lang.ClassNotFoundException: org.netbeans.lib.awtextra.AbsoluteLayout ERROR when java -jar jarfilename.jar
- elasticsearch - 修复 Kubernetes 中的弹性搜索损坏集群
- angular - 生成新的 Angular 应用程序会创建一个旧的 Angular 版本项目
- c# - 当“dotnet nuget push”失败时从 Github Packages 后端获取诊断信息?