项目中使用 ElasticSearch 作为全文检索的工具对文档等数据进行检索,客户反馈了部分问题
1.数字信息无法进行模糊查询
2.查询的匹配度排序与预期不符
针对第一个问题的排查,分词器确实不会对数字进行拆分
针对第二个问题,在不增加词库的情况下,即使是 standard 分词器,通过 match、match_phrase、match_phrase_prefix 也无法解决。
经查询资料,可以使用ngram分词器来自定义分词操作。
在 Elasticsearch 中,ngram 分词器是一种基于 n-gram 算法的分词器,用于将文本转换为一组 n-gram 词项。与其他一些分词器(如 standard 分词器)不同,ngram 分词器可以生成部分单词,并且不需要完整的词汇表。
ngram 分词器的工作原理是将输入文本切分成一个个较小的子字符串,然后将这些子字符串作为词项添加到索引中。
分词器接收以下参数:
- min_gram: 以gram为单位的最小字符长度,默认值为 1
- max_gram:以gram为单位的最大字符长度,默认值为 2
- token_chars:令牌(分词结果)中包含的字符类型,默认是全部类型。字符类型可以是以下几种类型:
- letter —保留字母类型,如a,b,c, 京
- digit —保留数字类型,如1,2
- whitespace —保留空格类型,如 " " or “\n”
- punctuation —保留标点类型,如 ! or "
- symbol —保留符号类型,如 $ or √
- custom —保留自定义类型,使用custom_token_chars设置自定义的字符
- custom_token_chars:自定义的字符将视为令牌的一部分
注意:将 min_gram 和 max_gram 设置为相同的值通常是有意义的。
min_gram值越小,匹配的文档就越多,但匹配出来的文档相关性质量就越低。
max_gram值越长, 匹配的文档就越少,但匹配出来的文档相关性质量就越高。
通常:min_gram 长度为 3是一个很好的起点
索引级别max_ngram_diff参数控制最大允许的差异,max_gram的值不能超过。
创建索引的时候,先在 setting 中创建自定义的analyzer,然后在创建 mapping时指定创建的analyzer即可
PUT attachment-test
{
"settings": {
"index.max_ngram_diff":"10",
"analysis": {
"analyzer": {
"ngram_analyzer":{
"tokenizer":"ngram_tokenizer"
}
},
"tokenizer": {
"ngram_tokenizer":{
"type":"ngram",
"min_gram":1,
"max_gram":10,
"token_chars":[
"letter","digit"
]
}
}
}
},
"mappings": {
"_meta":{
"dataId":"主数据Id",
"dataGlobalId":"主数据全局Id",
"fileId":"文件Id",
"fileName":"文件名称",
"title":"标题",
"type":"所属类型"
},
"properties": {
"dataId":{
"type": "long"
},
"dataGlobalId":{
"type": "keyword"
},
"fileId": {
"type": "keyword"
},
"fileName": {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"keyword":{
"type":"keyword"
},
"standard":{
"type":"text",
"analyzer": "ngram_analyzer"
}
}
},
"title": {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"keyword":{
"type":"keyword"
},
"standard":{
"type":"text",
"analyzer": "ngram_analyzer"
}
}
},
"type": {
"type": "keyword"
},
"document": {
"properties": {
"content": {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"standard":{
"type":"text",
"analyzer": "ngram_analyzer"
}
}
}
}
}
}
}
}