写在前面
在开始介绍字符过滤器,我们还是先回顾一下上一节,聊到的分词器
结构。
分词器有三个主要的需求:记号化
,标准化
,自定义分词器
,在Elasticsearch
中,为了处理这样的三个需求,首先定义了一个Analyzer接口,通过模板方法
的模式,来自定义相关功能的处理流程和方式,之后对于记号化和标准化,通过三种类型的过滤器,依次进行处理。
今天,就让我们聊下三种类型的过滤器的字符过滤器
字符过滤器
在es官网上,是这么介绍字符过滤器的
Character filters are used to preprocess the stream of characters before it is passed to the tokenizer.
在字节流进入分词之前,对字节流进行处理。
A character filter receives the original text as a stream of characters and can transform the stream by adding, removing, or changing characters.
因此,字节过滤器接收的是源文本,使用上吗,它可以对字节流进行增删改。
Elasticsearch has a number of built in character filters which can be used to build custom analyzers
es提供一些内置的字节过滤器,用来提供给用户自定义文本的分词器。
过滤器 | 标识 | 功能作用 |
---|---|---|
HTML Strip Character Filter | html_strip | HTML文本处理,去除HTML标签,或者对标签进行decode |
Mapping Character Filter | mapping | 对文本进行字符串的替换 |
Pattern Replace Character Filter | pattern_replace | 正则表达式方式对字符串文本进行替换 |
Character Filter用法演示
首先,我们先看一下Character Filter的使用方式,之后我们从源码角度看一下Character Filter是如何工作的。
验证分词过滤器效果
GET /_analyze
{
"tokenizer": "keyword",
"char_filter": [
"html_strip"
],
"text": "<p>I'm so <b>happy</b>!</p>"
}
复制代码
返回结果:
I'm so happy!
复制代码
通过验证,html_strip将文本中的'
编码成了单引号'
,并且去除p标签
和b标签
分词器中使用
在使用中,我们可以通过索引的settings配置,为索引配置对应的分词器
PUT /my-index-000001
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "keyword",
"char_filter": [
"html_strip"
]
}
}
}
}
}
复制代码
自定义标签
至此我们知道字节过滤器的作用和使用方式,如果你担心有些html标签你想保留,例如b标签,但是使用html_strip
会把所有的html标签进行无差别去除。那么是不是有其他过滤器可以达成这种效果?或者说html_strip
过滤器能不能让我们指定某些参数呢?
PUT my-index-000001
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "keyword",
"char_filter": [
"my_custom_html_strip_char_filter"
]
}
},
"char_filter": {
"my_custom_html_strip_char_filter": {
"type": "html_strip",
"escaped_tags": [
"b"
]
}
}
}
}
}
复制代码
通过上述的代码,我们可以得出两个信息。
我们可以对字符过滤器进行自定义
。如上,我们自定义了名称为my_custom_html_strip_char_filter
的过滤器,这个过滤器在html_strip过滤器的基础上,把b标签排除在外了。并且分词器能够包含很多个字节过滤器。
字节过滤器可以接收参数
。或者说过滤器指定了一些参数,例如html_strip过滤器的参数escaped_tags
,用来处理特殊的需求。
那么自定义中的参数是怎么生效的?字符过滤器的原理是什么样的,让我们通过源码一点一点来揭开这个面纱。
源码
下载源码:elasticsearch github
项目结构如下,过滤器等代码在modules
下,有时间我们分析一下es的项目目录结构,方便你更容易阅读源码。今天我们先把中心放在html_strip
字符过滤器是怎么工作的。
进入modules有一个通用分词器目录,如图
在这个module下找到HtmlStripCharFilterFactory
终于主角出现了:
解析HtmlStripCharFilterFactory
我们终于看到了我们熟悉的参数,escaped_tags
通过create方法,可以看到最终es的HTMLStripCharFilter
使用的是Lucene
的HTMLStripCharFilter类
,因此,我们还要下载Lucene源码。
如下是Lucene中HTMLStripCharFilter
构造器
把escapedTag加入到集合java private CharArraySet escapedTags = null;
中
html_strip流程
在上面,我们已经把escaped_tags传入了escapedTags,并且已经生成了HTMLStripCharFilter对象,进行html标签处理。那么具体是如何使用的呢,我们继续看。
HTMLStripCharFilter重写了
Reader
的方法,用来读取索引文本的字节流,其中重点在nextChar()
这七百多行代码,就是读取的流程,也是处理标签的流程。
在这个方法里是一个while(true)
循环,对读取的字节流进行处理。
这里通过改变字节的状态来标识是否需要排除。状态包含如下
具体如何通过标识,来达成标签的移除和排除,我们下节再介绍,点关注,有更多精彩。