ElasticSearch "H & R Block" 带有部分词搜索
ElasticSearch "H & R Block" with partial word search
要求是能够搜索到以下词条:
- "H & R" 找到 "H & R Block".
我已经设法单独使用 word_delimiter 实现了这个要求,正如这个答案 elasticsearch tokenize "H&R Blocks" as "H", "R", "H&R", "Blocks"
中提到的
使用 ruby 代码:
{
char_filter: {
strip_punctuation: { type: "mapping", mappings: [".=>", ",=>", "!=>", "?=>"] },
},
filter: {
my_splitter: {
type: "word_delimiter",
preserve_original: true
}
},
analyzer: {
my_analyzer {
char_filter: %w[strip_punctuation],
type: "custom",
tokenizer: "whitespace",
filter: %w[lowercase asciifolding my_splitter]
}
}
}
而且,在同一个查询中,我们需要自动完成功能或部分单词匹配,所以
- "Ser"、"Serv"、"Servi"、"Servic" 和 "Service" 都可以找到 "Service" 和 "Services"。
我已经成功地使用 ngram 单独实现了这个要求。
{
char_filter: {
strip_punctuation: { type: "mapping", mappings: [".=>", ",=>", "!=>", "?=>"] }
},
analyzer: {
my_analyzer: {
char_filter: %w[strip_punctuation],
tokenizer: "my_ngram",
filter: %w[lowercase asciifolding]
}
},
tokenizer: {
my_ngram: {
type: "nGram",
min_gram: "3",
max_gram: "10",
token_chars: %w[letter digit]
}
}
}
我只是无法同时实施它们。当我使用 ngram 时,短词会被忽略,所以 "H & R" 被忽略了。当我使用 word_delimiter 时,部分单词搜索停止工作。下面,我最近尝试合并这两个要求,结果支持部分单词搜索但不支持 "H & R"。
{
char_filter: {
strip_punctuation: { type: "mapping", mappings: [".=>", ",=>", "!=>", "?=>"] }
},
filter: {
my_splitter: {
type: "word_delimiter",
preserve_original: true
}
},
analyzer: {
my_analyzer: {
char_filter: %w[strip_punctuation],
type: "custom",
tokenizer: "my_tokenizer",
filter: %w[lowercase asciifolding my_splitter]
}
},
tokenizer: {
my_tokenizer: {
type: "nGram",
min_gram: "3",
max_gram: "10",
token_chars: %w[letter digit]
}
}
}
您可以使用映射中的 multi_field
以多种方式为同一字段编制索引。您可以在默认字段上使用带有自定义分词器的全文搜索,并为您的自动完成需求创建一个特殊的索引。
"title": {
"type": "string",
"fields": {
"raw": { "type": "string", "index": "not_analyzed" }
}
}
执行自动完成时,您的查询需要略有不同,因为字段将是 title.raw
而不是 title
.
一旦字段以对您的查询有意义的所有方式编入索引,您就可以使用布尔 "should" 查询来查询索引,匹配标记化版本和单词开始查询。很可能应该为第一个匹配完整单词的查询提供更大的提升,以获得顶部的直接命中。
要求是能够搜索到以下词条:
- "H & R" 找到 "H & R Block".
我已经设法单独使用 word_delimiter 实现了这个要求,正如这个答案 elasticsearch tokenize "H&R Blocks" as "H", "R", "H&R", "Blocks"
中提到的使用 ruby 代码:
{
char_filter: {
strip_punctuation: { type: "mapping", mappings: [".=>", ",=>", "!=>", "?=>"] },
},
filter: {
my_splitter: {
type: "word_delimiter",
preserve_original: true
}
},
analyzer: {
my_analyzer {
char_filter: %w[strip_punctuation],
type: "custom",
tokenizer: "whitespace",
filter: %w[lowercase asciifolding my_splitter]
}
}
}
而且,在同一个查询中,我们需要自动完成功能或部分单词匹配,所以
- "Ser"、"Serv"、"Servi"、"Servic" 和 "Service" 都可以找到 "Service" 和 "Services"。
我已经成功地使用 ngram 单独实现了这个要求。
{
char_filter: {
strip_punctuation: { type: "mapping", mappings: [".=>", ",=>", "!=>", "?=>"] }
},
analyzer: {
my_analyzer: {
char_filter: %w[strip_punctuation],
tokenizer: "my_ngram",
filter: %w[lowercase asciifolding]
}
},
tokenizer: {
my_ngram: {
type: "nGram",
min_gram: "3",
max_gram: "10",
token_chars: %w[letter digit]
}
}
}
我只是无法同时实施它们。当我使用 ngram 时,短词会被忽略,所以 "H & R" 被忽略了。当我使用 word_delimiter 时,部分单词搜索停止工作。下面,我最近尝试合并这两个要求,结果支持部分单词搜索但不支持 "H & R"。
{
char_filter: {
strip_punctuation: { type: "mapping", mappings: [".=>", ",=>", "!=>", "?=>"] }
},
filter: {
my_splitter: {
type: "word_delimiter",
preserve_original: true
}
},
analyzer: {
my_analyzer: {
char_filter: %w[strip_punctuation],
type: "custom",
tokenizer: "my_tokenizer",
filter: %w[lowercase asciifolding my_splitter]
}
},
tokenizer: {
my_tokenizer: {
type: "nGram",
min_gram: "3",
max_gram: "10",
token_chars: %w[letter digit]
}
}
}
您可以使用映射中的 multi_field
以多种方式为同一字段编制索引。您可以在默认字段上使用带有自定义分词器的全文搜索,并为您的自动完成需求创建一个特殊的索引。
"title": {
"type": "string",
"fields": {
"raw": { "type": "string", "index": "not_analyzed" }
}
}
执行自动完成时,您的查询需要略有不同,因为字段将是 title.raw
而不是 title
.
一旦字段以对您的查询有意义的所有方式编入索引,您就可以使用布尔 "should" 查询来查询索引,匹配标记化版本和单词开始查询。很可能应该为第一个匹配完整单词的查询提供更大的提升,以获得顶部的直接命中。