问题发现
最近在给es插入文档的时候,忽然报错,提示如下:
ElasticsearchException[Elasticsearch exception [type=illegal_argument_exception, reason=startOffset must be non-negative, and endOffset must be >= startOffset, and offsets must not go backwards startOffset=0,endOffset=3,lastStartOffset=3 for field 'title.pinyin']]
感觉是在用ik拼音分词的时候报的错。
排查过程
并不是所有的文档在插入的时候会报错,只有在title字段包含特殊符号的时候会报错,上网查了一下原因,说是ik拼音插件的错误,只需要升级一下插件的版本即可。
然而因为用的是阿里云的es服务,不能对插件进行升级,所以这个方法行不通。
也有说是因为,将参数“ignore_pinyin_offset”设置为false后,并向pinyin分词字段批量写入数据,即会出现“startOffset must be non-negative, and endOffset must be >= startOffset, and offsets must not go backwards”异常。所以将ignore_pinyin_offset设为true即可。
设置前的配置:
"my_pinyin": {
"keep_first_letter": "false",
"ignore_pinyin_offset": "false",
"keep_joined_full_pinyin": "true",
"lowercase": "true", "padding_char": " ",
"first_letter": "prefix",
"keep_original": "true",
"remove_duplicated_term": "true",
"keep_separate_first_letter": "false",
"type": "pinyin", "keep_full_pinyin": "false"
}
设置后的配置:
"my_pinyin": {
"keep_first_letter": "false",
"ignore_pinyin_offset": "true",
"keep_joined_full_pinyin": "true",
"lowercase": "true",
"padding_char": " ",
"first_letter": "prefix",
"keep_original": "true",
"remove_duplicated_term": "true",
"keep_separate_first_letter": "false",
"type": "pinyin",
"keep_full_pinyin": "false"
}
改完之后重新索引一遍文件,结果还是报这个错。
问题解决
就这么折腾了两天之后,发现既然这是这个版本的本身的bug,然后阿里云那边又不给升级版本,那为什么不曲线救国呢?
前面一开始排查的时候发现,是标题含有特殊符号的时候,才会出现这个bug,那么可以在拼音分词之前,再加一个filter,把特殊符号过滤掉,自然就没问题了。
于是我先配置了一个filter:
"specialCharactersFilter": {
"pattern": "\\p{Punct}",
"type": "pattern_replace",
"replacement": ""
}
然后再把这个filter配置到analyzer里:
"ik_pinyin_analyzer": {
"filter": [
"specialCharactersFilter",
"my_pinyin"
],
"type": "custom",
"tokenizer": "ik_smart"
}
这样,在用ik_pinyin_analyzer分词之前,会先通过specialCharactersFilter的正则表达式过滤,把所有的特殊符号都过滤掉,然后再用my_pinyin进行拼音分词。
这么处理后,就不会出现上面出现的错误了。
注:上述配置都是个性化配置,得根据自己的习惯和要求来配置,不用照搬,只要是加个新建一个filter然后加到pinyin前即可。