我开始学习Elasticsearch,现在我正在尝试编写我的第一个分析器配置。我想要实现的是,如果它们位于单词的开头或结尾,则会找到子字符串。如果我有“stackoverflow”这个词并且我搜索“stack”我想找到它,当我搜索“flow”时我想找到它,但是我不想要找到它搜索“ackov”(在我的用例中这没有意义)。
我知道有“Edge n gram tokenizer”,但是一个分析器只能有一个标记器,边缘n-gram可以是正面或背面(但不能同时进行)。
如果我理解正确,将两个版本的“Edge ngram 过滤器”(正面和背面)应用到分析器,那么我也找不到,因为两个过滤器都需要返回true,不是吗?因为“堆栈”不在单词的结尾,所以后边缘n克过滤器将返回false并且不会找到单词“stackoverflow”。
那么,如何配置我的分析器在一个单词的结尾或开头找到子字符串,而不是在中间?
答案 0 :(得分:2)
可以做的是定义两个分析器,一个用于在字符串的开头匹配,另一个用于在字符串的末尾匹配。在下面的索引设置中,我将前一个prefix_edge_ngram_analyzer
命名为后者suffix_edge_ngram_analyzer
。这两个分析器可以应用于text.prefix
子字段的多字段字符串字段,分别应用于text.suffix
字符串字段。
{
"settings": {
"analysis": {
"analyzer": {
"prefix_edge_ngram_analyzer": {
"tokenizer": "prefix_edge_ngram_tokenizer",
"filter": ["lowercase"]
},
"suffix_edge_ngram_analyzer": {
"tokenizer": "keyword",
"filter" : ["lowercase","reverse","suffix_edge_ngram_filter","reverse"]
}
},
"tokenizer": {
"prefix_edge_ngram_tokenizer": {
"type": "edgeNGram",
"min_gram": "2",
"max_gram": "25"
}
},
"filter": {
"suffix_edge_ngram_filter": {
"type": "edgeNGram",
"min_gram": 2,
"max_gram": 25
}
}
}
},
"mappings": {
"test_type": {
"properties": {
"text": {
"type": "string",
"fields": {
"prefix": {
"type": "string",
"analyzer": "prefix_edge_ngram_analyzer"
},
"suffix": {
"type": "string",
"analyzer": "suffix_edge_ngram_analyzer"
}
}
}
}
}
}
}
然后我们假设我们索引以下测试文档:
PUT test_index/test_type/1
{ "text": "stackoverflow" }
然后我们可以使用以下查询通过前缀或后缀进行搜索:
# input is "stack" => 1 result
GET test_index/test_type/_search?q=text.prefix:stack OR text.suffix:stack
# input is "flow" => 1 result
GET test_index/test_type/_search?q=text.prefix:flow OR text.suffix:flow
# input is "ackov" => 0 result
GET test_index/test_type/_search?q=text.prefix:ackov OR text.suffix:ackov
使用查询DSL查询的另一种方法:
POST test_index/test_type/_search
{
"query": {
"multi_match": {
"query": "stack",
"fields": [ "text.*" ]
}
}
}
<强>更新强>
如果您已有字符串字段,则可以将其“升级”为多字段,并使用其分析器创建两个必需的子字段。这样做的方法是按顺序执行此操作:
关闭索引以创建分析器
POST test_index/_close
更新索引设置
PUT test_index/_settings
{
"analysis": {
"analyzer": {
"prefix_edge_ngram_analyzer": {
"tokenizer": "prefix_edge_ngram_tokenizer",
"filter": ["lowercase"]
},
"suffix_edge_ngram_analyzer": {
"tokenizer": "keyword",
"filter" : ["lowercase","reverse","suffix_edge_ngram_filter","reverse"]
}
},
"tokenizer": {
"prefix_edge_ngram_tokenizer": {
"type": "edgeNGram",
"min_gram": "2",
"max_gram": "25"
}
},
"filter": {
"suffix_edge_ngram_filter": {
"type": "edgeNGram",
"min_gram": 2,
"max_gram": 25
}
}
}
}
重新打开索引
POST test_index/_open
最后,更新文本字段的映射
PUT test_index/_mapping/test_type
{
"properties": {
"text": {
"type": "string",
"fields": {
"prefix": {
"type": "string",
"analyzer": "prefix_edge_ngram_analyzer"
},
"suffix": {
"type": "string",
"analyzer": "suffix_edge_ngram_analyzer"
}
}
}
}
}
您仍然需要重新索引所有文档,以便填充和分析新的子字段text.prefix
和text.suffix
。