文章目录
-
- 1 analysis与analyzer
-
- 1.1 内置的分词器
- 1.2 内置分词器示例
- 1.3 中文分词
-
- 1.3.1 IK分词器
- 1.3.2 HanLP
- 1.3.3 pinyin分词器
- 1.4 中文分词演示
- 1.5 分词的实际应用
-
- 1.5.1 设置mapping
- 1.5.2 插入数据
- 1.5.3 查询
- 1.6 拼音分词器
-
- 1.6.1 设置settings
- 1.6.2 设置mapping
- 1.6.3 数据的插入
- 1.6.4 查询
- 1.7 自定义中文、拼音混合分词器
-
- 1.7.1 设置settings
- 1.7.2 mappings设置
- 1.7.3 添加数据
- 1.7.4 查询
- 2 spring boot与Elasticsearch的整合
-
- 2.1 添加依赖
- 2.2 获取ElasticsearchTemplate
- 2.3 定义Movie实体类
- 2.4 查询
1 analysis与analyzer
analysis(只是一个概念),文本分析是将全文本转换为一系列单词的过程,也叫分词。analysis是通过analyzer(分词器)来实现的,可以使用Elasticsearch内置的分词器,也可以自己去定制一些分词器。除了在数据写入的时候将词条进行转换,那么在查询的时候也需要使用相同的分析器对语句进行分析。
anaylzer是由Character Filter、Tokenizer和Token Filter三部分组成,例如有
Hello a World, the world is beautiful
:
- Character Filter: 将文本中html标签剔除掉。
- Tokenizer: 按照规则进行分词,在英文中按照空格分词。
- Token Filter: 去掉stop world(停顿词,a, an, the, is, are等),然后转换小写。
1.1 内置的分词器
分词器名称 | 处理过程 |
---|---|
Standard Analyzer | 默认的分词器,按词切分,小写处理 |
Simple Analyzer | 按照非字母切分(符号被过滤),小写处理 |
Stop Analyzer | 小写处理,停用词过滤(the, a, this) |
Whitespace Analyzer | 按照空格切分,不转小写 |
Keyword Analyzer | 不分词,直接将输入当做输出 |
Pattern Analyzer | 正则表达式,默认是\W+(非字符串分隔) |
1.2 内置分词器示例
例如:
A. Standard Analyzer
GET _analyze
{
"analyzer": "standard",
"text": "2 Running quick brown-foxes leap over lazy dog in the summer evening"
}
B. Simple Analyzer
GET _analyze
{
"analyzer": "simple",
"text": "2 Running quick brown-foxes leap over lazy dog in the summer evening"
}
1.3 中文分词
中文分词在所有的搜索引擎中都是一个很大的难点,中文的句子应该是切分成一个个的词,一句中文,在不同的上下文中,其实是有不同的理解,例如下面这句话:
这个苹果不大好吃/这个苹果不大好吃
1.3.1 IK分词器
IK分词器支持自定义词库,支持热更新分词字典,地址为 https://github.com/medcl/elasticsearch-analysis-ik
elasticsearch-plugin.bat install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.3.0/elasticsearch-analysis-ik-6.3.0.zip
安装步骤:
- 下载zip包,下载路径为:https://github.com/medcl/elasticsearch-analysis-ik/releases
- 在Elasticsearch的plugins目录下创建名为 analysis-ik 的目录,将下载好的zip包解压在该目录下
- 在dos命令行进入Elasticsearch的bin目录下,执行 elasticsearch-plugin.bat list 即可查看到该插件
IK分词插件对应的分词器有以下几种:
- ik_smart
- ik_max_word
1.3.2 HanLP
安装步骤如下:
- 下载ZIP包,下载路径为:https://pan.baidu.com/s/1mFPNJXgiTPzZeqEjH_zifw#list/path=%2F,密码i0o7
- 在Elasticsearch的plugins目录下创建名为 analysis-hanlp 的目录,将下载好的zip包解压在该目录下.
- 下载词库,地址为:https://github.com/hankcs/HanLP/releases
- 将analyzer-hanlp目录下的data目录删掉,然后将词库 data-for-1.7.5.zip 解压到anayler-hanlp目录下
- 将 第2步 解压目录下的 config 文件夹中两个文件 hanlp.properties hanlp-remote.xml 拷贝到ES的家目录中的config目录下 analysis-hanlp 文件夹中(analyzer-hanlp 目录需要手动去创建)。
- 将课件 中hanlp文件夹中提供的六个文件拷贝到 $ES_HOME\plugins\analysis-hanlp\data\dictionary\custom 目录下。
HanLP对应的分词器如下:
- hanlp,默认的分词
- hanlp_standard,标准分词
- hanlp_index,索引分词
- hanlp_nlp,nlp分词
- hanlp_n_short,N-最短路分词
- hanlp_dijkstra,最短路分词
- hanlp_speed,极速词典分词
1.3.3 pinyin分词器
安装步骤:
- 下载ZIP包,下载路径为:https://github.com/medcl/elasticsearch-analysis-pinyin/releases
- 在Elasticsearch的plugins目录下创建名为 analyzer-pinyin 的目录,将下载好的zip包解压在该目录下.
1.4 中文分词演示
ik_smart
GET _analyze
{
"analyzer": "ik_smart",
"text": ["剑桥分析公司多位高管对卧底记者说,他们确保了唐纳德·特朗普在总统大选中获胜"]
}
hanlp
GET _analyze
{
"analyzer": "hanlp",
"text": ["剑桥分析公司多位高管对卧底记者说,他们确保了唐纳德·特朗普在总统大选中获胜"]
}
1.5 分词的实际应用
在如上列举了很多的分词器,那么在实际中该如何应用?
1.5.1 设置mapping
要想使用分词器,先要指定我们想要对那个字段使用何种分词,如下所示:
PUT customers
{
"mappings": {
"properties": {
"content": {
"type": "text",
"analyzer": "hanlp_index"
}
}
}
}
1.5.2 插入数据
POST customers/_bulk
{"index":{}}
{"content":"如不能登录,请在百端登录百度首页,点击【登录遇到问题】,进行找回密码操作"}
{"index":{}}
{"content":"网盘客户端访问隐藏空间需要输入密码方可进入。"}
{"index":{}}
{"content":"剑桥的网盘不好用"}
1.5.3 查询
GET customers/_search
{
"query": {
"match": {
"content": "密码"
}
}
}
1.6 拼音分词器
在查询的过程中我们可能需要使用拼音来进行查询,在中文分词器中我们介绍过 pinyin 分词器,那么在实际的工作中该如何使用呢?
1.6.1 设置settings
PUT /medcl
{
"settings" : {
"analysis" : {
"analyzer" : {
"pinyin_analyzer" : {
"tokenizer" : "my_pinyin"
}
},
"tokenizer" : {
"my_pinyin" : {
"type" : "pinyin",
"keep_separate_first_letter" : false,
"keep_full_pinyin" : true,
"keep_original" : true,
"limit_first_letter_length" : 16,
"lowercase" : true,
"remove_duplicated_term" : true
}
}
}
}
}
如上所示,我们基于现有的拼音分词器定制了一个名为 pinyin_analyzer 这样一个分词器。可用的参数可以参照:https://github.com/medcl/elasticsearch-analysis-pinyin
拼音分词器可选参数解析:
属性名 | 解释 |
---|---|
keep_first_letter | 值为true时: 将所有汉字的拼音首字母拼接到一起:李小璐 -> lxl |
keep_full_pinyin | 值为true:在最终的分词结果中,会出现每个汉字的全拼:李小璐 -> li , xiao, lu |
keep_none_chinese | 值为true时: 是否保留非中文本,例如 java程序员, 在最终的分词结果单独出现 java |
keep_separate_first_lett | 值为true时: 在最终的分词结果单独将每个汉字的首字母作为一个结果:李小璐 -> l, y |
keep_joined_full_pinyin | 值为true时:在最终的分词结果中将所有汉字的拼音放到一起:李小璐 -> liuyan |
keep_none_chinese_in_joined_full_pinyin | 值为true时:将非中文内容文字和中文汉字拼音拼到一起 |
none_chinese_pinyin_tokenize | 值为true时: 会将非中文按照可能的拼音进行拆分:wvwoxvlu -> w, v, wo, x, v, lu |
keep_original | 值为true时: 保留原始的输入 |
remove_duplicated_term | 值为true时: 移除重复 |
1.6.2 设置mapping
PUT medcl/_mapping
{
"properties": {
"name": {
"type": "keyword",
"fields": {
"pinyin": {
"type": "text",
"analyzer": "pinyin_analyzer",
"boost": 10
}
}
}
}
}
1.6.3 数据的插入
POST medcl/_bulk
{"index":{}}
{"name": "刘德华"}
{"index":{}}
{"name": "张学友"}
{"index":{}}
{"name": "四大天王"}
{"index":{}}
{"name": "柳岩"}
{"index":{}}
{"name": "angel baby"}
1.6.4 查询
GET medcl/_search
{
"query": {
"match": {
"name.pinyin": "ldh"
}
}
}
1.7 自定义中文、拼音混合分词器
1.7.1 设置settings
PUT goods
{
"settings": {
"analysis": {
"analyzer": {
"hanlp_standard_pinyin":{
"type": "custom",
"tokenizer": "hanlp_standard",
"filter": ["my_pinyin"]
}
},
"filter": {
"my_pinyin": {
"type" : "pinyin",
"keep_separate_first_letter" : false,
"keep_full_pinyin" : true,
"keep_original" : true,
"limit_first_letter_length" : 16,
"lowercase" : true,
"remove_duplicated_term" : true
}
}
}
}
}
1.7.2 mappings设置
PUT goods/_mapping
{"properties": {
"content": {
"type": "text",
"analyzer": "hanlp_standard_pinyin"
}
}
}
1.7.3 添加数据
POST goods/_bulk
{"index":{}}
{"content":"如不能登录,请在百端登录百度首页,点击【登录遇到问题】,进行找回密码操作"}
{"index":{}}
{"content":"网盘客户端访问隐藏空间需要输入密码方可进入。"}
{"index":{}}
{"content":"剑桥的网盘不好用"}
1.7.4 查询
GET goods/_search
{
"query": {
"match": {
"content": "caozuo"
}
},
"highlight": {
"pre_tags": "<em>",
"post_tags": "</em>",
"fields": {
"content": {}
}
}
}
2 spring boot与Elasticsearch的整合
2.1 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2.2 获取ElasticsearchTemplate
@Configuration
public class ElasticsearchConfig extends ElasticsearchConfigurationSupport {
@Bean
public Client elasticsearchClient() throws UnknownHostException {
Settings settings = Settings.builder().put("cluster.name", "my-application").build();
TransportClient client = new PreBuiltTransportClient(settings);
client.addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
return client;
}
@Bean(name = {"elasticsearchTemplate"})
public ElasticsearchTemplate elasticsearchTemplate() throws UnknownHostException {
return new ElasticsearchTemplate(elasticsearchClient(), entityMapper());
}
// use the ElasticsearchEntityMapper
@Bean
@Override
public EntityMapper entityMapper() {
ElasticsearchEntityMapper entityMapper = new ElasticsearchEntityMapper(elasticsearchMappingContext(),
new DefaultConversionService());
entityMapper.setConversions(elasticsearchCustomConversions());
return entityMapper;
}
}
2.3 定义Movie实体类
@Document(indexName = "movies", type = "_doc")//movies是elasticsearch的索引
public class Movie {
private String id;
private String title;
private Integer year;,
private List<String> genre;
// setters and getters
}
2.4 查询
@RestController
@RequestMapping("/movie")
public class MovieController {
private ElasticsearchTemplate elasticsearchTemplate;
public MovieController( ElasticsearchTemplate elasticsearchTemplate) {
this.elasticsearchTemplate = elasticsearchTemplate;
}
@GetMapping
public Object getMovies(){
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(new RangeQueryBuilder("year").from(2016).to(2017))
.build();
List<Movie> movieList = elasticsearchTemplate.queryForList(searchQuery, Movie.class);
return movieList;
}
}