让搜索引擎更懂你-Elasticsearch自定义分词开发实践

本文介绍了Elasticsearch(ES)的倒排索引和分词原理,阐述了自定义分词如何解决模糊查询性能低和精确查询匹配问题。通过自定义分词服务开发,实现了无需重启集群即可动态更新分词词典,提高了查询效率和准确性。

1.为什么使用ES

ES(Elasticsearch)作为一个开源的高扩展的分布式全文检索引擎,自2016年起已经超过Solr,成为排名第一的搜索引擎应用,具有很多独特的优点。

  1. 可以为几乎所有类型的数据提供近实时的索引、搜索和分析服务。无论是结构化或非结构化数据文本、数值数据、还是地理空间数据,ES都支持高效地存储和索引,并快速的提供搜索。
  2. 本身扩展性很好。可以扩展到上百台服务器,处理PB级别的数据,由于索引具有副本机制,所以它也具有高可用优点。
  3. 它的使用简单。通过简单的RESTful API隐藏了Lucene的复杂性,从而让全文搜索变得简单易用。

2.什么是自定义分词

在说ES自定义分词之前,首先要弄清楚ES的倒排索引和分词原理。

2.1 倒排索引

ES每个分片都是一个Luence,Luence基于倒排索引进行搜索。在弄清楚倒排索引之前,先了解一下正排索引。正排索引存在于我们生活的方方面面,比如图书馆中,找一本书的流程是先找到哪个科室,哪个书架,第几层,从哪边数第几本才能找到我们想要的那本书。通过这个例子可以看出,正排索引是文档ID(可以理解为科室、书架)到文档内容、单词(可以理解为书)的关联关系。

如果我们在图书馆查询带有Elasticsearch字样的书籍时候,正排索引会找对应类型的科室、书架,最后找到很多书,再逐个查看哪一本带有Elasticsearch字样。可以想象,当图书馆的书足够多时,正排索引的查询会变得很慢。倒排索引解决了正排索引出现的问题,当我们查询带有Elasticsearch字样的书籍时,可以根据Elasticsearch这个词,直接找到对应的书的id,它是单词到文档Id的关联关系。

倒排索引建立的是分词(Term)和文档(Document)之间的映射关系,在倒排索引中,数据是面向词(Term)而不是面向文档的。

一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,都会有一个包含它的文档列表。

2.2 分词

ES是基于倒排索引的一种搜索引擎,倒排索引的关键就是分词(Term),在往索引中插入数据的时候,ES会把文本转换成一系列单词(Term or Token),这个过程就是分词,也叫做文本分析,在ES里面称为Analysis。

在ES中,分词器(Analyzer)是专门用来分词的组件,它负责对写入的文本数据按照一定的规则进行分词。Analyzer主要有字符过滤器(Character Filters)、分词器(Tokenizer)和token过滤器(Token Filters)组成。

1.字符过滤器(Character Filters)

字符过滤器以字符流的形式接收原始⽂本,并可以通过添加、删除或更改字符来转换,比如去除html特殊标记符。⼀个Analyzer可能有0个或多个字符过滤器

2.分词器(Tokenizer)

对原始文本按照一定规则进行切词。⽐如使⽤whitespace分词器,当遇到空格的时候会将⽂本拆分成token。“eating an apple” >> [eating, an, apple]。⼀个分析器有且仅有⼀个分词器。

3.Token过滤器(To

### easy-es 中实现自定义分词器的方法 在 `easy-es` 框架中,要实现自定义分词器,可以基于 Elasticsearch自定义分词器机制进行扩展。以下是详细的说明: #### 1. 自定义分词器的概念 Elasticsearch 提供了一个名为 **custom analyzer** 的功能,允许开发者根据业务需求定义自己的分词逻辑[^1]。这种分词器通常由以下三部分组成: - 字符过滤器 (Character Filters):用于预处理输入文本中的字符。 - 分词器 (Tokenizer):负责将字符串拆分为词汇单元。 - 词条过滤器 (Token Filters):进一步修改或筛选已生成的词汇单元。 #### 2. 在 `easy-es` 中配置自定义分词器 `easy-es` 是一个封装了 Elasticsearch 功能的 Java 工具库,在其框架下可以通过设置索引的方式引入自定义分词器。具体操作如下所示: ##### 定义自定义分词器 首先需要在 Elasticsearch 的索引配置中声明一个新的分词器。例如,假设我们需要创建一个基于 IK 分词器的增强版分词器,可以在索引设置中这样定义: ```json { "analysis": { "analyzer": { "my_custom_analyzer": { "type": "custom", "tokenizer": "ik_max_word", "filter": ["lowercase", "asciifolding"] } } } } ``` 在此例子中,“my_custom_analyzer” 使用了 IK 分词器 (`ik_max_word`) 并附加了一些词条过滤器(如转换为小写和 ASCII 折叠)。这一步骤对应于 Elasticsearch 原生 API 的方式[^3]。 ##### 将自定义分词器集成到 `easy-es` 当使用 `easy-es` 创建索引时,可通过 `LambdaEsIndexWrapper` 类来指定字段使用的分词器。下面是一个完整的代码示例: ```java @GetMapping("/createCustomAnalyzerIndex") public Object createCustomAnalyzerIndex() { LambdaEsIndexWrapper<User> wrapper = new LambdaEsIndexWrapper<>(); // 设置索引名称 wrapper.indexName("users_with_custom_analyzer"); // 映射字段并应用自定义分词器 wrapper.mapping( User::getContent, FieldType.TEXT, Analyzer.CUSTOM_ANALYZER_NAME // 替换为实际的自定义分词器名称 ); // 添加自定义分词器至 settings Map<String, Object> analysisSettings = new HashMap<>(); Map<String, Object> customAnalyzer = new HashMap<>(); customAnalyzer.put("type", "custom"); customAnalyzer.put("tokenizer", "ik_max_word"); // 可替换为你想要的基础 tokenizer customAnalyzer.put("filter", Arrays.asList("lowercase", "asciifolding")); analysisSettings.put("analyzer.my_custom_analyzer", customAnalyzer); wrapper.addAnalysisSetting(analysisSettings); // 其他常规配置... wrapper.settings(3, 2); // shards 和 replicas 数量 return userMapper.createIndex(wrapper); } ``` 注意这里的 `CUSTOM_ANALYZER_NAME` 应该匹配你在 JSON 配置中定义的名字 “my_custom_analyzer”。 #### 3. 测试自定义分词效果 完成以上步骤后,你可以通过 `_analyze` 接口测试新分词器的效果。例如发送请求给 Elasticsearch 如下: ```bash POST /_analyze { "analyzer": "my_custom_analyzer", "text": "这是一个测试" } ``` 如果一切正常工作,则返回的结果应该展示按照预期规则被分解后的 token 列表。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值