SpringBoot整合ES

SpringBoot整合ES

Elasticsearch

分布式全文搜索引擎 ES检索原理

  1. 将数据库信息拆分为多个词-------分词

  2. 分词后每个词作为关键字,通过关键字得到ID,加载ID的同时加载ID的部分数据

  3. 通过关键字找到ID后,显示该ID的数据,其实也是通过索引的形式来查询数据,根据关键字查ID,再由ID查数据(倒排索引)

 

  • 倒排索引:通过关键字找到相应ID,再由ID找到数据

  • 创建文档:每一个关键字对应的ID和数据称为一个文档

  • 使用文档:输入关键字之后根据ID找到对应信息

ES下载安装

Download Elasticsearch | Elastic

  • ES 7.x 及之前版本,选择 Java 8

  • ES 8.x 及之后版本,选择 Java 17 或者 Java 18,建议 Java 17,因为对应版本的 Logstash 不支持 Java 18

  • Java 9、Java 10、Java 12 和 Java 13 均为短期版本,不推荐使用

  • M1(Arm) 系列 Mac 用户建议选择 ES 7.8.x 以上版本,因为考虑到 ELK 不同产品自身兼容性,7.8.x以上版本原生支持 Arm 原生 JDK

ES索引操作

创建索引

  • 注意,索引唯一,不允许重复

 

获取索引

 

删除索引

 

IK分词器

Releases · medcl/elasticsearch-analysis-ik · GitHub

创建索引并指定规则

{
    "mappings":{
        "properties" :{
            "id":{
                "type":"keyword"
            },
            "name":{
                "type":"text",
                "analyzer":"ik_max_word",
                "copy_to":"all"
            },
            "type":{
              "type":"keyword"
            },
            "desciption":{
                "type":"text",
                "analyzer":"ik_max_word",
                "copy_to":"all"
            },
            "all":{
                "type":"text",
                "analyzer":"ik_max_word"
            }
        }
    }
}

ES文档操作

为索引创建文档

http://localhost:9200/books/_doc(随机生成ID)

 

  • _doc中返回结果中的ID为随机生成的,不需要自己在请求体中添加ID

http://localhost:9200/books/_doc/id(指定ID)

 

创建索引文档__create

http://localhost:9200/books/_create/id(指定ID)

 

  • 注意,create后面需要添加指定ID

查询文档

查询全部文档

http://localhost:9200/books/_search

 

条件查询

http://localhost:9200/books/_search?q=name:springboot

 

修改文档
  • 建议将所有属性全部添加到请求体中,不然会全覆盖(即变成只有请求体中的属性)

 

修改单个属性

http://localhost:9200/books/_update/2(POST)

  • 修改的信息以文档的形式存在,也就是修改文档中的属性,而不是改一个文档

springboot整合ES

  • 添加依赖(低版本,不推荐使用)

     <!--低级别的elasticsearch客户端-->
     <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
     </dependency>

    yml配置

    elasticsearch:
        rest:
          uris:  http://localhost:9200
    使用
@Autowired
private ElasticsearchRestTemplate esTemplate;
@test
public void test() throws Exception{
    esTemplate.使用方法
}
  • 添加依赖(高版本)

 <dependency>-->
           <groupId>org.elasticsearch.client</groupId>
         <artifactId>elasticsearch-rest-high-level-client</artifactId>
      </dependency>
  1. yml不需要配置

  2. 自己创建客户端

     @Autowired
        private RestHighLevelClient client;
    ​
        @Test
        public void testConnect() throws IOException {
            HttpHost host = HttpHost.create("http://localhost:9200");//客户端的url
            RestClientBuilder builder = RestClient.builder(host);
            client = new RestHighLevelClient(builder);
    ​
            client.close();//需要自己关闭客户端
        }

3.创建客户端之后我们就可以自己去创建索引

 @Test
    // 创建索引
    public void testCreateIndex() throws IOException {
        CreateIndexRequest request = new CreateIndexRequest("books");
        client.indices().create(request, RequestOptions.DEFAULT);
    }

4.每次我们创建索引或者做别的操作都需要创建客户端和关闭客户端,这是繁琐的,我们可以在每次操作前进行客户端的创建

 @BeforeEach
    void setUp() {
        objectMapper = new ObjectMapper();
        HttpHost host = HttpHost.create("http://localhost:9200");
        RestClientBuilder builder = RestClient.builder(host);
        client = new RestHighLevelClient(builder);
    }

5.操作后进行客户端的关闭

@AfterEach
    void tearDown() throws IOException {
        client.close();
    }
  • 这两个方法的测试类自己提供的,只需要在方法里添加你自己的业务代码即可

创建文档

//创建文档
    @Test
    public void testCreateDoc() throws Exception {
        Book book = bookMapper.selectById(1);
        IndexRequest request = new IndexRequest("books").id(book.getId() + "");
        String jsonParams = objectMapper.writeValueAsString(book);
        request.source(jsonParams, XContentType.JSON);
        client.index(request, RequestOptions.DEFAULT);
    }
 

将数据库的数据都存入es中

 @Test
    // 将mysql数据库tbl_book表中的数据都存到es中
    public void testCreateDocAllFromMySQL() throws Exception {
        List<Book> books = bookMapper.selectList(null);
        // 批处理请求,相当于一个request容器,可以把单个请求加进来
        BulkRequest requests = new BulkRequest();
        for (Book book : books) {
            IndexRequest request = new IndexRequest("books").id(book.getId() + "");
            String jsonParams = objectMapper.writeValueAsString(book);//objectMapper是json转换工具
            request.source(jsonParams, XContentType.JSON);
            requests.add(request);
        }
        client.bulk(requests, RequestOptions.DEFAULT);
    }

json转换工具

package top.jacktgq.utils;
​
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
​
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
​
/**
 * @author GG
 * @Description 使用jackson进行json转换的工具类
 * @version 1.0.0
 * @date 2021/2/8 21:50
 */
public class CandyJsonUtils {
    private final static ObjectMapper objectMapper = new ObjectMapper();
​
    public static ObjectMapper getInstance() {
        return objectMapper;
    }
​
    /**
     * 转换为 JSON 字符串
     *
     * @param obj
     * @return
     * @throws Exception
     */
    public static String obj2json(Object obj) throws Exception {
        return objectMapper.writeValueAsString(obj);
    }
​
    /**
     * 转换为 JSON 字符串,忽略空值
     *
     * @param obj
     * @return
     * @throws Exception
     */
    public static String obj2jsonIgnoreNull(Object obj) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        return mapper.writeValueAsString(obj);
    }
​
    /**
     * 转换为 JavaBean
     *
     * @param jsonString
     * @param clazz
     * @return
     * @throws Exception
     */
    public static <T> T json2pojo(String jsonString, Class<T> clazz) throws Exception {
        objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
        return objectMapper.readValue(jsonString, clazz);
    }
​
    /**
     * 字符串转换为 Map<String, Object>
     *
     * @param jsonString
     * @return
     * @throws Exception
     */
    public static <T> Map<String, Object> json2map(String jsonString) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        return mapper.readValue(jsonString, Map.class);
    }
​
    /**
     * 字符串转换为 Map<String, T>
     */
    public static <T> Map<String, T> json2map(String jsonString, Class<T> clazz) throws Exception {
        Map<String, Map<String, Object>> map = (Map<String, Map<String, Object>>) objectMapper.readValue(jsonString, new TypeReference<Map<String, T>>() {
        });
        Map<String, T> result = new HashMap<String, T>();
        for (Map.Entry<String, Map<String, Object>> entry : map.entrySet()) {
            result.put(entry.getKey(), map2pojo(entry.getValue(), clazz));
        }
        return result;
    }
​
    /**
     * 深度转换 JSON 成 Map
     *
     * @param json
     * @return
     */
    public static Map<String, Object> json2mapDeeply(String json) throws Exception {
        return json2MapRecursion(json, objectMapper);
    }
​
    /**
     * 把 JSON 解析成 List,如果 List 内部的元素存在 jsonString,继续解析
     *
     * @param json
     * @param mapper 解析工具
     * @return
     * @throws Exception
     */
    private static List<Object> json2ListRecursion(String json, ObjectMapper mapper) throws Exception {
        if (json == null) {
            return null;
        }
​
        List<Object> list = mapper.readValue(json, List.class);
​
        for (Object obj : list) {
            if (obj != null && obj instanceof String) {
                String str = (String) obj;
                if (str.startsWith("[")) {
                    obj = json2ListRecursion(str, mapper);
                } else if (obj.toString().startsWith("{")) {
                    obj = json2MapRecursion(str, mapper);
                }
            }
        }
​
        return list;
    }
​
    /**
     * 把 JSON 解析成 Map,如果 Map 内部的 Value 存在 jsonString,继续解析
     *
     * @param json
     * @param mapper
     * @return
     * @throws Exception
     */
    private static Map<String, Object> json2MapRecursion(String json, ObjectMapper mapper) throws Exception {
        if (json == null) {
            return null;
        }
​
        Map<String, Object> map = mapper.readValue(json, Map.class);
​
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Object obj = entry.getValue();
            if (obj != null && obj instanceof String) {
                String str = ((String) obj);
​
                if (str.startsWith("[")) {
                    List<?> list = json2ListRecursion(str, mapper);
                    map.put(entry.getKey(), list);
                } else if (str.startsWith("{")) {
                    Map<String, Object> mapRecursion = json2MapRecursion(str, mapper);
                    map.put(entry.getKey(), mapRecursion);
                }
            }
        }
​
        return map;
    }
​
    /**
     * 将 JSON 数组转换为集合
     *
     * @param jsonArrayStr
     * @param clazz
     * @return
     * @throws Exception
     */
    public static <T> List<T> json2list(String jsonArrayStr, Class<T> clazz) throws Exception {
        JavaType javaType = getCollectionType(ArrayList.class, clazz);
        List<T> list = (List<T>) objectMapper.readValue(jsonArrayStr, javaType);
        return list;
    }
​
​
    /**
     * 获取泛型的 Collection Type
     *
     * @param collectionClass 泛型的Collection
     * @param elementClasses  元素类
     * @return JavaType Java类型
     * @since 1.0
     */
    public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
        return objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
    }
​
    /**
     * 将 Map 转换为 JavaBean
     *
     * @param map
     * @param clazz
     * @return
     */
    public static <T> T map2pojo(Map map, Class<T> clazz) {
        return objectMapper.convertValue(map, clazz);
    }
​
    /**
     * 将 Map 转换为 JSON
     *
     * @param map
     * @return
     */
    public static String mapToJson(Map map) {
        try {
            return objectMapper.writeValueAsString(map);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }
​
    /**
     * 将 JSON 对象转换为 JavaBean
     *
     * @param obj
     * @param clazz
     * @return
     */
    public static <T> T obj2pojo(Object obj, Class<T> clazz) {
        return objectMapper.convertValue(obj, clazz);
    }
}

查询

  @Test
    // 按ID查询
    public void testGet() throws IOException {
        GetRequest request = new GetRequest("books", "1");//索引名,id
        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        System.out.println("book:" + response.getSourceAsString());
    }

条件查询

 @Test
    public void testSearch() throws IOException {
        SearchRequest request = new SearchRequest("books");
​
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(QueryBuilders.termQuery("all", "spring"));
        request.source(builder);
​
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
    }

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值