Elasticsearch:synonym_graph 与自定义分析器中的停止过滤器之间的意外交互
Elasticsearch: Unexpected interaction between synonym_graph and stop filter in custom analyzer
描述
我正在尝试使用包含停用词的多词同义词进行查询。
先举个例子来解释一下吧。
我已将以下文档编入索引。
- foo
- 栏
- 富吧
- foo of bar
- fb
查询 {"query":{"match":{"test":{"query":"foo of bar"}}}}
的预期结果是 return 文档:
- 富吧
- foo of bar
- fb
配置
在这个例子中,我得到了 2 个过滤器:
- stop: 将删除令牌of
- synonym_graph: 处理同义词fb, foo bar, foo of bar
映射
{
"properties": {
"test": {
"type": "text",
"analyzer": "test_index_analyzer",
"search_analyzer": "test_search_analyzer"
}
}
设置
{
"settings" : {
"index": {
"number_of_shards": 1,
"number_of_replicas": 0,
"analysis": {
"analyzer": {
"test_index_analyzer": {
"type": "custom",
"tokenizer": "whitespace",
"filter": [
"english_stop"
]
},
"test_search_analyzer": {
"type": "custom",
"tokenizer": "whitespace",
"filter": [
"english_stop",
"english_syn"
]
}
},
"filter": {
"english_stop": {
"type": "stop",
"stopwords": "_english_",
"ignore_case": true,
"remove_trailing": false
},
"english_syn": {
"type": "synonym_graph",
"synonyms": [
"fb,foo of bar",
"fb,foo bar"
]
}
}
}
}
}
}
结果
token format: "token,start_offset-end_offset,type / position / positionLength"
Query
Search Result
index analysys
Search analysys
fb
fb
fb,0-2,word,0,1
foo,0-2,SYNONYM / 0 / 1
foo,0-2,SYNONYM / 0 / 3
fb,0-2,word / 0 / 4
bar,0-2,SYNONYM / 2 / 2
bar,0-2,SYNONYM / 3 / 1
foo of bar
fb
foo,0-3,word,0,1
bar,7-10,word,2,1
fb,0-10,SYNONYM / 0 / 3
foo,0-3,word / 0 / 1
bar,7-10,word / 2 / 1
foo bar
fb,foo bar
foo,0-3,word,0,1
bar,4-7,word,1,1
fb,0-7,SYNONYM / 0 / 2
foo,0-3,word / 0 / 1
bar,4-7,word / 1 / 1
所有搜索都期望 return 3 行:
- fb
- 富吧
- foo of bar
注意:bar 的 foo 永远不会 returned
我的猜测是 foo of bar 被停止过滤器索引到位置 [foo, ,bar] 并且同义词正在寻找 [foo, bar]。
你对实现我的目标有什么建议吗?
当您使用停用词过滤器时,单词的位置将被保留,因此如果您检查分析器结果中的 foo of bar,您将得到以下结果:
{
"tokens" : [
{
"token" : "foo",
"start_offset" : 0,
"end_offset" : 3,
"type" : "word",
"position" : 0
},
{
"token" : "bar",
"start_offset" : 7,
"end_offset" : 10,
"type" : "word",
"position" : 2
}
]
}
如您所见,您在零位置获得 'foo' 令牌,在二位置获得 'bar',因此您的同义词过滤器无法找到该文档。
要解决您的问题,您应该首先应用同义词过滤器,然后删除停用词,如下所示。
"test_search_analyzer": {
"type": "custom",
"tokenizer": "whitespace",
"filter": [
"english_syn",
"english_stop"
]
}
您应该将 'foo bar, foo of bar' 添加到您的同义词列表中。
我认为保留停用词是必要的,因为它可以帮助获得更精确的搜索结果(尤其是与ES使用的BM25相似度。),您可以查看elasticsearch官方文章here。
描述
我正在尝试使用包含停用词的多词同义词进行查询。 先举个例子来解释一下吧。
我已将以下文档编入索引。
- foo
- 栏
- 富吧
- foo of bar
- fb
查询 {"query":{"match":{"test":{"query":"foo of bar"}}}}
的预期结果是 return 文档:
- 富吧
- foo of bar
- fb
配置
在这个例子中,我得到了 2 个过滤器:
- stop: 将删除令牌of
- synonym_graph: 处理同义词fb, foo bar, foo of bar
映射
{
"properties": {
"test": {
"type": "text",
"analyzer": "test_index_analyzer",
"search_analyzer": "test_search_analyzer"
}
}
设置
{
"settings" : {
"index": {
"number_of_shards": 1,
"number_of_replicas": 0,
"analysis": {
"analyzer": {
"test_index_analyzer": {
"type": "custom",
"tokenizer": "whitespace",
"filter": [
"english_stop"
]
},
"test_search_analyzer": {
"type": "custom",
"tokenizer": "whitespace",
"filter": [
"english_stop",
"english_syn"
]
}
},
"filter": {
"english_stop": {
"type": "stop",
"stopwords": "_english_",
"ignore_case": true,
"remove_trailing": false
},
"english_syn": {
"type": "synonym_graph",
"synonyms": [
"fb,foo of bar",
"fb,foo bar"
]
}
}
}
}
}
}
结果
token format: "token,start_offset-end_offset,type / position / positionLength"
Query | Search Result | index analysys | Search analysys |
---|---|---|---|
fb | fb | fb,0-2,word,0,1 | foo,0-2,SYNONYM / 0 / 1 foo,0-2,SYNONYM / 0 / 3 fb,0-2,word / 0 / 4 bar,0-2,SYNONYM / 2 / 2 bar,0-2,SYNONYM / 3 / 1 |
foo of bar | fb | foo,0-3,word,0,1 bar,7-10,word,2,1 |
fb,0-10,SYNONYM / 0 / 3 foo,0-3,word / 0 / 1 bar,7-10,word / 2 / 1 |
foo bar | fb,foo bar | foo,0-3,word,0,1 bar,4-7,word,1,1 |
fb,0-7,SYNONYM / 0 / 2 foo,0-3,word / 0 / 1 bar,4-7,word / 1 / 1 |
所有搜索都期望 return 3 行:
- fb
- 富吧
- foo of bar
注意:bar 的 foo 永远不会 returned
我的猜测是 foo of bar 被停止过滤器索引到位置 [foo, ,bar] 并且同义词正在寻找 [foo, bar]。
你对实现我的目标有什么建议吗?
当您使用停用词过滤器时,单词的位置将被保留,因此如果您检查分析器结果中的 foo of bar,您将得到以下结果:
{
"tokens" : [
{
"token" : "foo",
"start_offset" : 0,
"end_offset" : 3,
"type" : "word",
"position" : 0
},
{
"token" : "bar",
"start_offset" : 7,
"end_offset" : 10,
"type" : "word",
"position" : 2
}
]
}
如您所见,您在零位置获得 'foo' 令牌,在二位置获得 'bar',因此您的同义词过滤器无法找到该文档。
要解决您的问题,您应该首先应用同义词过滤器,然后删除停用词,如下所示。
"test_search_analyzer": {
"type": "custom",
"tokenizer": "whitespace",
"filter": [
"english_syn",
"english_stop"
]
}
您应该将 'foo bar, foo of bar' 添加到您的同义词列表中。
我认为保留停用词是必要的,因为它可以帮助获得更精确的搜索结果(尤其是与ES使用的BM25相似度。),您可以查看elasticsearch官方文章here。