我正在尝试建立一个ElasticSearch索引,该索引将包含带有产品名称的文档,例如笔记本电脑-
{ "name" : "Laptop Blue I7"}
然后我想通过查询ES索引将其用于自动完成建议。我有两个主要限制条件:
我想为术语定义同义词,例如“笔记本电脑”的“笔记本” 提取的文档可以是以下类型-
"Laptop Blue I7"
"Laptop Blue I7"
"Laptop Blue I7"
"Laptop Blue I7"
"Laptop Red I7"
"Laptop Red I7"
"Notebook Blue I7"
现在,我在创建索引时添加以下设置和映射文件-
{
"settings": {
"index": {
"analysis": {
"filter" : {
"synonym" : {
"type" : "synonym",
"synonyms" : ["Laptop,Notebook"]
}
},
"analyzer": {
"synonym" : {
"tokenizer" : "keyword",
"filter" : ["synonym"]
}
}}}},
"mappings": {
"catalog": {
"properties": {
"name": {
"type": "text",
"analyzer": "synonym"
}
}
}
}
}
当我使用“笔记本”查询数据时, 首选响应应按照频率和同义词排序。但是,当我查询时,响应通常与同义词和频率无关。我使用以下查询-
/_search
{"query": {
"query_string" : {"default_field" : "name", "query" : "Notebook"}
} }
我得到的答复是-
"Notebook Blue I7"
虽然我希望响应是以下任一-
"Laptop Blue I7"
"Laptop Red I7"
或
"Notebook Blue I7"
"Laptop Blue I7"
"Laptop Red I7"
解决此问题的任何见解都会有所帮助。谢谢
========= 编辑1:
当我在“笔记本”上使用\_analyze
时,响应为
{'tokens': [{'end_offset': 3,
'position': 0,
'start_offset': 0,
'token': 'Notebook',
'type': '<ALPHANUM>'},
{'end_offset': 3,
'position': 0,
'start_offset': 0,
'token': 'Laptop',
'type': 'SYNONYM'}]}
答案 0 :(得分:2)
问题与您的keyword
分析器中使用的synonym
令牌生成器一起使用。请执行以下操作来调试您的问题。
如果在反向索引中为您的文档生成的标记与从搜索词生成的标记匹配,那么elasticsearch将显示它与之匹配,并解释查询提供了许多其他信息,例如分片中有多少个文档与搜索词及其搜索词匹配得分等
以上只是解决问题的非常基本的步骤,但是您尚未实施适当的自动完成搜索,因此,在这种情况下,应返回note
和lapt
的结果。要实现此功能,您需要使用edge n gram
分析器,并且this ES官方帖子可以帮助您实现此功能。
如果您遇到任何其他问题或需要任何说明,请告诉我。
答案 1 :(得分:1)
正如阿米特(Amit)所述,您应该考虑实现自动完成edge n gram
。我想解释一下为什么您使用的设置不能对完整的单词Notebook
起作用,而该单词在查询时没有产生预期的结果。为此,让我们了解上面的分析器将如何工作。
在设置中定义的synonym
分析器具有两个组成部分,tokenizer
和令牌filter
。对于输入字符串,首先将使用分词器。令牌生成器的输出将是令牌。然后,这些将用作令牌filter
的输入,并产生最终的令牌集。
您可以详细了解分析器的工作原理here。
Laptop Blue I7
对于此输入字符串,首先将应用keyword
标记符,并且您可能已经知道关键字标记符会采用输入字符串并生成一个与原始输入字符串相同的标记,而无需进行任何修改。因此,tokenizer的输出将是Laptop Blue I7
作为单个令牌。现在,此令牌将用作synonym
令牌过滤器的输入。根据定义,Laptop
和Notebook
是同义词,但是它们都不与令牌Laptop Blue I7
匹配,因此最终此过滤器将不执行任何操作,并将令牌原样传递。因此,最终生成的令牌将为Laptop Blue I7
。
因此,当您搜索Notebook
时,它将与上述具有name
值的文档不匹配。
请注意,如果输入字符串仅为Laptop
或Notebook
,则将获得预期的令牌,因为关键字令牌生成器将为输入生成单个单词令牌。这就是为什么_analyze在“笔记本”上为您提供预期结果的原因。
因此,结论是keyword
是这里的罪魁祸首。为了解决这个问题,我们需要一个令牌生成器,它将生成单独的令牌,分别为laptop
,blue
,i7
,最简单的解决方法是使用standard
而不是{{1 }}。
此answer可能会对您有所帮助。