Spring Boot使用docker整合ElasticSearch ik分词搜索和拼音搜索

2,900 阅读2分钟

前面的blog已经处理完Spring Boot和docker安装配置ElasticSearch,这篇blog主要讲一下使用docker安装ElasticSearch ik分词器和拼音搜索功能。

准备工作

安装ik分词器

我们直接使用elasticsearch-plugin安装ik分词器

// 进入elasticsearch容器
docker exec -it elasticsearch /bin/bash

// 安装ik分词器7.8.0
 ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.8.0/elasticsearch-analysis-ik-7.8.0.zip

安装过程如下:

安装ik分词器

安装pinyin插件

和ik分词器一样我们同样使用elasticsearch-plugin安装pinyin插件

// 安装ik分词器7.8.0
 ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-pinyin/releases/download/v7.8.0/elasticsearch-analysis-pinyin-7.8.0.zip

在这里插入图片描述
检查一下plugins目录查看是否安装成功,准备工作就完成了。
检查plugins目录

Spring Boot进行分词和拼音查询

前面已经完成了一部分编码工作了,请查看Spring Boot 使用docker整合ElasticSearch,那么这次我们就继续在上次的基础上改造,使其支持拼音和分词搜索。

创建setting和mapping文件

文件存放在resource目录下,为了方便区分,所以我新建了一个elasticsearch目录。

文件目录
elasticsearch_mapping.json文件内容

{
  "block": {
    "properties": {
      "userName": {
        "type": "text",
        "analyzer": "pinyin_analyzer",
        "search_analyzer": "pinyin_analyzer",
        "fields": {
          "pinyin": {
            "type": "string",
            "ignore_above": 256
          }
        }
      },
      "sex": {
        "type": "keyword",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "age": {
        "type": "keyword",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      }
    }
  }
}

elasticsearch_setting.json文件内容

{
  "index": {
    "analysis": {
      "analyzer": {
        "pinyin_analyzer": {
          "tokenizer": "my_pinyin"
        }
      },
      "tokenizer": {
        "my_pinyin": {
          "type": "pinyin",
          "keep_first_letter": true,
          "keep_separate_first_letter": false,
          "keep_full_pinyin": true,
          "keep_original": true,
          "limit_first_letter_length": 16,
          "lowercase": true,
          "remove_duplicated_term": true
        }
      }
    }
  }
}

将setting和mapping配置到UserEntity中

如果之前已经创建了索引了,则需要删除,或者重新创建新的所有才能创建分词和拼音相关索引,支持分词和拼音搜索

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.data.elasticsearch.annotations.Mapping;
import org.springframework.data.elasticsearch.annotations.Setting;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Setting(settingPath = "classpath:elasticsearch/elasticsearch_setting.json")
@Mapping(mappingPath = "classpath:elasticsearch/elasticsearch_mapping.json")
@Document(indexName = "user")
public class UserEntity {

    @Id
    private Long userId;

    @Field(type = FieldType.Text, analyzer = "pinyin", searchAnalyzer = "pinyin")
    private String userName;

    @Field(type = FieldType.Keyword)
    private Integer age;

    @Field(type = FieldType.Keyword)
    private Integer sex;

}

编写测试类

依旧是在之前的测试类基础上进行编写,首先执行save方法批量插入一些数据方便测试,然后执行searchByUserName查看结果。

import com.example.elasticsearch.entity.UserEntity;
import com.example.elasticsearch.service.ElasticSearchService;
import com.example.elasticsearch.util.StringUtils;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

import javax.annotation.Resource;

@SpringBootTest
class ElasticsearchApplicationTests {

    @Resource
    private ElasticSearchService elasticSearchService;

	/**
     * @Author David
     * @Description 批量插入测试数据
     **/
    @Test
    void save() {
        List<String> randomName = StringUtils.getRandomName(100);
        List<UserEntity> list = new ArrayList<>(100);
        for (int i = 0; i < randomName.size(); i++) {
            UserEntity userEntity = UserEntity.builder()
                    .userId(i + 1L).userName(randomName.get(i)).age(ThreadLocalRandom.current().nextInt(50))
                    .sex(ThreadLocalRandom.current().nextInt(2))
                    .build();
            list.add(userEntity);
        }
        elasticSearchService.saveUser(list);
    }
	
	/**
     * @Author David
     * @Description 根据id搜索
     **/
    @Test
    void findById() {
        UserEntity byId = elasticSearchService.findById(1L);
        System.out.println(byId);
    }

	/**
     * @Author David
     * @Description 搜索
     **/
    @Test
    void searchByUserName() {
        List<UserEntity> da = elasticSearchService.searchByUserName("wpt");
        System.out.println(da);
        List<UserEntity> da1 = elasticSearchService.searchByUserName("闻平涂");
        System.out.println(da1);
    }

}
// searchByUserName output
[UserEntity(userId=7, userName=闻平涂, age=44, sex=1)]
[UserEntity(userId=7, userName=闻平涂, age=44, sex=1)]

总结

ElasticSearch使用非常广泛,支持的场景也非常多,除了分词和拼音之外,还有像繁体搜索,以及高亮显示都用的比较多,后面一一梳理,如果对你有帮助记得关注支持一下哦,这是我前进的最大动力!