🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,
15年
工作经验,精通Java编程
,高并发设计
,Springboot和微服务
,熟悉Linux
,ESXI虚拟化
以及云原生Docker和K8s
,热衷于探索科技的边界,并将理论知识转化为实际应用。保持对新技术的好奇心,乐于分享所学,希望通过我的实践经历和见解,启发他人的创新思维。在这里,我希望能与志同道合的朋友交流探讨,共同进步,一起在技术的世界里不断学习成长。
技术合作请加本人wx(注明来自csdn):foreast_sea
【Elasticsearch】内置分词器和IK分词器
引言
在当今数字化信息爆炸的时代,全文搜索技术成为了我们获取所需信息的关键工具。无论是在搜索引擎中查找资料,还是在企业内部系统中检索文档,全文搜索都发挥着至关重要的作用。而在全文搜索的背后,文本分析扮演着核心角色。
文本分析,简单来说,就是将文本内容转换为可被搜索的词项的过程。想象一下,一篇长篇文档包含了大量的文字,搜索引擎如何能快速准确地找到与用户查询相关的内容呢?这就需要通过文本分析,把文档中的文本切割成一个个有意义的词项,建立索引,当用户发起查询时,能够迅速匹配到相应的词项,从而返回相关的文档。
Elasticsearch作为一款强大的分布式搜索和分析引擎,提供了丰富的文本分析功能,其中分词器是关键组件之一。分词器决定了如何将文本拆分成词项,不同的分词器有着不同的工作原理和分词规则,适用于各种不同的场景。同时,为了满足特定语言和业务需求,我们还可以引入第三方分词器,如IK分词器。
在这篇博文中,我们将深入探讨Elasticsearch的内置分词器和IK分词器。首先,我们会详细了解内置分词器的工作原理、使用方式以及它们的特点。然后,我们将一步步介绍如何下载、集成和使用IK分词器,通过实际的Java API案例展示其强大功能。通过本文的学习,你将对Elasticsearch
的分词机制有更深入的理解,能够根据具体的业务需求选择合适的分词器,提升全文搜索的效果和性能。
一、Elasticsearch 简介
Elasticsearch是一个基于Lucene的分布式、RESTful风格的搜索和数据分析引擎。它旨在快速地存储、搜索和分析大量的数据,被广泛应用于各种领域,如日志分析、电商搜索、企业内容管理等。
Elasticsearch的核心优势在于其分布式架构,能够处理PB级别的数据,并提供高可用性和可扩展性。它通过将数据分片存储在多个节点上,实现数据的并行处理和容错能力。同时,Elasticsearch
提供了简单易用的RESTful API
,方便开发者进行数据的索引、搜索和管理。
1.1 核心概念
- 索引(Index):类似于关系型数据库中的数据库概念,是一组文档的集合。每个索引都有自己的映射(Mapping),定义了文档的结构和字段类型。
- 文档(Document):是Elasticsearch中存储的基本数据单元,类似于关系型数据库中的一行记录。文档以JSON格式存储,包含一个或多个字段。
- 类型(Type):在早期版本中,一个索引可以包含多个类型,用于区分不同结构的文档。但从Elasticsearch 7.0开始,逐渐弃用了类型的概念,一个索引通常只包含一种类型的文档。
- 分片(Shard):索引被分成多个分片,每个分片是一个独立的Lucene索引。分片可以分布在不同的节点上,实现数据的并行处理和水平扩展。
- 副本(Replica):为了提高数据的可用性和搜索性能,每个分片可以有多个副本。副本会自动同步主分片的数据,当主分片出现故障时,副本可以自动提升为主分片。
1.2 全文搜索原理
在Elasticsearch中,全文搜索的实现依赖于倒排索引(Inverted Index)。倒排索引是一种数据结构,它将文档中的每个词项映射到包含该词项的文档列表。当用户发起查询时,Elasticsearch首先对查询语句进行分词,然后在倒排索引中查找匹配的词项,最后根据词项找到对应的文档,并根据相关性对文档进行排序,返回给用户。
二、Elasticsearch 内置分词器
Elasticsearch提供了多种内置分词器,每种分词器都有其独特的工作原理和适用场景。下面我们将详细介绍几种常用的内置分词器。
2.1 Standard 分词器
- 工作原理:Standard分词器是Elasticsearch默认的分词器,它基于Unicode文本分割算法,按照词的边界进行分词。它会将文本中的单词、数字、标点符号等分开,同时将所有词项转换为小写形式。
- 分词规则:
- 按照Unicode文本分割算法识别词的边界。
- 将所有词项转换为小写。
- 去除停用词(如“the”、“and”、“is”等),但默认情况下不启用停用词过滤。
- 特点:
- 通用性强,适用于大多数语言的文本分析。
- 简单高效,能够快速地对文本进行分词。
- 对英文文本的分词效果较好,但对于一些特殊语言(如中文),可能需要进一步的处理。
示例:
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
public class StandardAnalyzerExample {
public static void main(String[] args) throws Exception {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http")));
SearchRequest searchRequest = new SearchRequest("your_index");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("your_field", "This is a test sentence."));
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest);
SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
client.close();
}
}
在上述示例中,我们使用Standard分词器对文本“This is a test sentence.”进行分词,它会将其分成“this”、“is”、“a”、“test”、“sentence”等词项。
2.2 Whitespace 分词器
- 工作原理:Whitespace分词器简单地按照空白字符(如空格、制表符、换行符等)对文本进行分词,不会对词项进行任何转换或过滤。
- 分词规则:
- 以空白字符作为分隔符,将文本分割成词项。
- 保留词项的原始大小写形式。
- 特点:
- 非常简单直观,适用于需要保留原始词项格式的场景。
- 不进行词项的转换和过滤,可能会导致分词结果中包含一些无意义的词项(如标点符号)。
示例:
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
public class WhitespaceAnalyzerExample {
public static void main(String[] args) throws Exception {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http")));
SearchRequest searchRequest = new SearchRequest("your_index");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("your_field", "This is a test sentence."));
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest);
SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
client.close();
}
}
在这个示例中,Whitespace分词器会将文本“This is a test sentence.”分成“This”、“is”、“a”、“test”、“sentence”,保留了每个词项的原始大小写。
2.3 Keyword 分词器
- 工作原理:Keyword分词器不会对文本进行分词,而是将整个文本作为一个词项。它适用于需要精确匹配的场景,如ID字段、分类标签等。
- 分词规则:
- 将输入的文本作为一个整体词项。
- 不进行任何分词操作,保留原始文本。
- 特点:
- 适用于需要精确匹配的字段,如产品ID、用户ID等。
- 不进行分词,因此在搜索时不会进行词项的拆分和匹配,速度较快。
示例:
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
public class KeywordAnalyzerExample {
public static void main(String[] args) throws Exception {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http")));
SearchRequest searchRequest = new SearchRequest("your_index");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("your_field", "This is a test sentence."));
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest);
SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
client.close();
}
}
在这个例子中,Keyword分词器会将整个文本“This is a test sentence.”作为一个词项,在搜索时只有输入完全相同的文本才能匹配到。
2.4 其他内置分词器
除了上述三种分词器外,Elasticsearch还提供了许多其他内置分词器,如:
- Simple分词器:按照非字母字符对文本进行分词,并将词项转换为小写。
- Stop分词器:在Simple分词器的基础上,去除停用词。
- Snowball分词器:支持多种语言的词干提取,能够将单词还原为词干形式,提高搜索的召回率。
不同的分词器适用于不同的语言和业务场景,开发者需要根据具体需求选择合适的分词器。
三、IK分词器
IK分词器是一个开源的、基于Java的轻量级中文分词器,它在Elasticsearch中得到了广泛的应用。IK分词器提供了两种分词模式:细粒度(ik_smart)和粗粒度(ik_max_word),能够满足不同场景下的中文分词需求。
3.1 下载IK分词器
IK分词器的下载和安装步骤如下:
- 首先,确定你使用的Elasticsearch版本,IK分词器需要与Elasticsearch版本兼容。可以在IK分词器的官方GitHub仓库中查看版本对应关系。
- 下载适合你Elasticsearch版本的IK分词器插件。可以从GitHub仓库的发布页面下载对应的zip包。
- 将下载的zip包解压到Elasticsearch的plugins目录下。例如,如果你将Elasticsearch安装在/elasticsearch目录下,那么将解压后的文件放置在/elasticsearch/plugins/ik目录下。
- 重启Elasticsearch服务,使IK分词器插件生效。
3.2 集成IK分词器到Elasticsearch
在Elasticsearch中集成IK分词器非常简单,只需要在索引映射中指定使用IK分词器即可。以下是一个示例:
PUT /your_index
{
"mappings": {
"properties": {
"your_field": {
"type": "text",
"analyzer": "ik_smart",
"search_analyzer": "ik_smart"
}
}
}
}
在上述示例中,我们创建了一个名为your_index的索引,并在映射中定义了一个名为your_field的文本字段,指定使用ik_smart分词器进行索引和搜索时的分词。
3.3 使用IK分词器的Java API调用
在Java中使用IK分词器进行搜索,我们需要使用Elasticsearch的Java客户端。以下是一个完整的示例:
3.3.1 添加Maven依赖
首先,在你的项目的pom.xml文件中添加Elasticsearch的Java客户端依赖:
<dependencies>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.17.4</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.17.4</version>
</dependency>
</dependencies>
上述依赖中,elasticsearch-rest-high-level-client
是Elasticsearch的高级REST客户端,用于与Elasticsearch进行交互;httpclient
是Apache HttpClient库,用于处理HTTP请求;elasticsearch
是Elasticsearch的核心库。
3.3.2 代码示例
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
public class IKAnalyzerExample {
public static void main(String[] args) throws Exception {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http")));
SearchRequest searchRequest = new SearchRequest("your_index");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("your_field", "你好,世界"));
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest);
SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
client.close();
}
}
在上述代码中,我们使用Elasticsearch的Java客户端创建了一个搜索请求,查询名为your_index的索引中your_field字段包含“你好,世界”的文档。由于我们在索引映射中指定了使用ik_smart分词器,因此在搜索时会使用IK分词器对查询语句进行分词。
3.4 IK分词器的两种模式
- ik_smart(细粒度模式):这种模式会尽可能地将文本切分成最细粒度的词项,以提高搜索的准确性。例如,对于文本“中华人民共和国”,ik_smart模式会分成“中华人民共和国”。
- ik_max_word(粗粒度模式):这种模式会将文本切分成尽可能多的词项,以提高搜索的召回率。例如,对于文本“中华人民共和国”,ik_max_word模式会分成“中华”、“中华人民”、“中华人民共和国”、“人民”、“人民共和国”、“共和国”等词项。
开发者可以根据具体的业务需求选择合适的分词模式。
四、总结
在本文中,我们深入探讨了Elasticsearch的文本分析机制以及内置分词器和IK分词器的使用方法。理解文本分析在全文搜索中的核心作用是选择合适分词器的基础。
Elasticsearch的内置分词器提供了多种选择,适用于不同的语言和业务场景。Standard分词器通用性强,适用于大多数语言;Whitespace分词器简单直观,适用于保留原始词项格式的场景;Keyword分词器适用于精确匹配的字段。
而IK分词器则为中文文本分析提供了强大的支持。通过简单的下载、集成步骤,我们可以在Elasticsearch中轻松使用IK分词器,并通过Java API进行灵活的搜索操作。IK分词器的两种模式ik_smart和ik_max_word能够满足不同的搜索需求,提高搜索的准确性和召回率。
在实际项目中,我们需要根据具体的业务需求和数据特点,选择合适的分词器或组合使用多种分词器,以实现高效、准确的全文搜索功能。希望本文能够帮助你更好地理解和应用Elasticsearch的分词技术,提升你的搜索应用开发能力。
参考资料文献
- Elasticsearch官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
- IK分词器官方GitHub仓库:https://github.com/medcl/elasticsearch-analysis-ik
- 《Elasticsearch实战》,Ramnivas Laddad著
- 《Lucene实战》,Doug Cutting、Erik Hatcher著