正排索引
文档ID到文档内容、单词的关联关系。比如书的目录页对应正排索引(指明章节名称,指明页数)用于查看章节
倒排索引:
单词到文档ID的关联关系。比如索引页对应倒排索引(指明关键词、指明页数)用于关键词查找 倒排索引是搜索引擎的核心,主要包含两个部分: 单词词典(Term Dictionary)
- 记录所有文档的单词,一般都比较大
- 记录单词到倒排列表的关联信息
倒排列表(Posting List) 记录了单词对应的文档集合,由倒排索引项组成。倒排索引项包含如下信息:
- 文档ID,用于获取原始信息
- 单词频率,记录该单词在该文档中的出现次数,用于后续相关性算分
- 位置,记录单词在文档中的粉刺位置,用于做词语搜索
- 偏移,记录单词在文档的开始和结束位置,用于做高亮显示
分词
分词是指将文本转换成一系列单词的过程,也可以叫做文本分析,在es里面成为Analysis
分词器是Elasticsearch中专门处理分词的组件,英文为Analyzer,其组成如下: Character Filters 针对原始文本进行处理,比如去除html特殊标记符 Tokenizer 将原始文本按照一定规则切分为单词 Token Filters 针对Tokenizer处理的单词进行在加工,比如转小写,删除或新增等处理
Analyze_api Elasticsearch提供了一个测试分词的api接口,方便验证分词效果,endpoint是_analyze
- 可以直接指定Analyzer进行测试
- 可以直接指定索引中的字段进行测试
- 可以自定义分词器进行测试
Elasticsearch自带分词器
中文分词
难点:
- 中文分词指的是将一个汉字序列切分成一个一个单独的词,在英文中单词之间是以空格作为自然分隔符,但汉语中则没有形式上的分隔符
- 上下文不同分词效果迥异,比如交叉歧义问题,比如下面两种分词都合理
乒乓球拍/卖/完了 乒乓球/拍/买完了
常用分词系统
IK
- 实现中英文单词的切分,支持ik_smart、ik_maxword等模式
- 可自定义词库,支持热更新分词词典
- https://github.com/medcl/elasticsearch-analysis-ik
jieba
- python中最流行的分词系统,支持分词和词性标注
- 支持繁体分词,自定义词典,并行分词等
- https://github.com/sing1ee/elasticsearch-jieba-plugin
基于自然语言处理的分词系统
HanLp
- 由一系列模型与算法组成的Java工具包,目标是普及自然语言处理在生产环境中的应用
- https://github.com/hankcs/HanLp
thulac
- THU Lexical Analyzer for Chinese,由清华大学自然语言处理与社会人文计算实验室研制推出的一套中文词法分析工具包,具有中文分词和词性标注功能
- https://github.com/microbun/elasticsearch-thulac-plugin
自定义分词
当自带的分词无法满足需求时,可自定义分词 通过自定义Character Filters、Tokenizer、Token Filters实现
Character Filters
- 在Tokenizer之前对原始文本进行处理,比如增加、删除或替换字符等
- 自带的如下:
- HTML Strip 去除html标签和转换html实体
- Mapping进行字符替换操作
- Pattern Replace进行正则匹配替换
- 会影响后续Tokenizer解析的postion和offset信息
Tokenizer
- 将原始文本按照一定规则切分为单词(term or token)
- 自带的如下:
- standard 按照单词进行分割
- letter 按照非字符类进行分割
- whitespace 按照空格进行分割
- UAX URL Email 按照standard 分割,但不会分割邮箱和url
- NGram和Edge NGram连词分割
- Path Hierarchy 按照文件路径进行分割
Token Filters
- 对于Tokenizer输出的单词(term)进行增加、删除、修改等操作
- 自带的如下:
- lowercase 将所有的term转换为小写
- stop删除stop words
- NGram和Edge NGram连词分割
- Synonym添加近义词的term
自定义分词的api
自定义分词需要在索引的配置中设定,如下所示:
分词会在如下两个时机使用:
- 创建或更新文档时(Index Time),会对相应的文档进行分词处理
- 查询时(Search Time),会对查询语句进行分词
索引时分词是通过配置Index Mapping中每个字段的analyzer属性实现的,如下:
总结:
- 一般不需要特别指定查询时分词器,直接使用索引时分词器即可,否则会出现无法匹配的情况
- 明确字段是否需要分词,不需要分词的字段就将type设置为keyword,可以节省空间和提高写性能
- 善用_analyze API,查看文档的具体分词结果
参考: https://www.jianshu.com/p/625d553188b4