一张图展示我们要学的东西

Elasticsearch和solr区别

ES下载安装

前提是你要本地安装jdk1.8以上的版本
Elasticsearch 7.6.1学习(一)下载windows 版本的es,下载可视化界面,使用kibana

ES head 插件的安装

他是一个web的前段工具,需要有node环境。


打开这个app.js


将这个改为es的地址

cmd里面进入这个目录

npm  run  start


以上就启动了

以上就启动这个了

ES 内置的REST接口

利用Kibana 对es 进行crud

Kibana 是一个可视化工具,需要配置这个工具要连接的es的地址


默认是localhost ,如果是要操作服务器上面的es,那么就要改这个里面的地址了

核心概念

前提

es是有集群的,比如这个集群里面有3个,那么3个es是在不同的服务器上面。一个es 里面可以创建很多的索引,就是索引库,就相当于数据库,创建的时候会定义分片的个数。分为主分片和父分片。

举个例子,集群有3个,在不同的服务器上面。你创建一个索引库,这个索引里面有2个主分片,每一个主分片有1个父分片。那么这个索引是在3个服务器上面都有的,并且每一个主分片和他对应的父分片在不同的服务器上面,也就是每一个服务器上面的es里面保存的数据都是一样的,只是分片不一样。

cluster

Shards

Replicas

Gateway

JestClient 进行操作Elasticsearch6.6.x

导入依赖

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>



 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
 </dependency>



 <dependency>
            <groupId>io.searchbox</groupId>
            <artifactId>jest</artifactId>
            <version>6.3.1</version>
 </dependency>

配置文件

spring.elasticsearch.jest.uris=http://127.0.0.1:9200
spring.data.elasticsearch.cluster-nodes=localhost:9300
spring.data.elasticsearch.cluster-name=my-application

写实体类

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class people {

    private Integer id;

    private String name;

    private String phone;
}

写业务层,实现crud

创建索引库

@RestController
public class IndexController {
   

导入依赖,就可以直接使用
    @Autowired
    private JestClient jestClient;

    @GetMapping("createIndex")
    public String createIndex(String indexName) throws Exception{
   
        CreateIndex createIndex = new CreateIndex.Builder(indexName).build();

        System.out.println(createIndex);
        JestResult result = jestClient.execute(createIndex);
        return result.getJsonString();
    }

删除索引库

    @GetMapping("deleteIndex")
    public String deleteIndex(String indexName) throws Exception{
   
        DeleteIndex deleteIndex = new DeleteIndex.Builder(indexName).build();
        JestResult result = jestClient.execute(deleteIndex);
        return result.getJsonString();
    }

新增文档数据

  @GetMapping("creatDoc")
    public String creatDoc() throws Exception{
   

        people people = new people();
        people.setPhone("ddd");
        people.setName("iii");
        people.setId(55);
        Index.Builder builder = new Index.Builder(people);
        Index index = builder.index("people").type("peopledoc").build();
        JestResult result = jestClient.execute(index);
        return result.getJsonString();
    }

删除文档数据

 @GetMapping("deleteDoc")
    public String deleteDoc(String id) throws Exception{
   
        Delete index = new Delete.Builder(id).index("people").type("peopledoc").build();
        JestResult result = jestClient.execute(index);
        return result.getJsonString();
    }

查询文档数据

 @GetMapping("search")
    public String search(String Keyword) throws Exception{
   
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();


        searchSourceBuilder.query(new MultiMatchQueryBuilder(Keyword, "name","phone"));


        System.out.println(searchSourceBuilder.toString());


        SearchResult result = jestClient.execute(new Search.Builder(searchSourceBuilder.toString())
                .addIndex("people")
                .addType("peopledoc")
                .build());



        List<SearchResult.Hit<people, Void>> hits = result.getHits(people.class);


        for(SearchResult.Hit<people, Void> hit:  hits){
   
            people source = hit.source;

            System.out.println(source.getId());
            System.out.println(source.getPhone());
            System.out.println(source.getName());
            System.out.println("==============");
        }




        return result.getJsonString();
    }

实现分页模糊查询功能

es的索引库

创建索引库对应的实体类,并且创建一个返回结果的实体类

查询实体类


返回的结果实体类

之后开始写controller层和service层

controller层


service层



service层是业务层,里面的业务步骤是:

整个分页模糊查询的步骤就是这样:

1  将前段传过来的查询条件,封装为es的查询语句
2   JestClient jestClient这个依赖进行执行这个查询语句,得到结果
3   将结果进行解析,封装为前段要的格式返回给前段

封装es查询语句

公共时间函数

// 结束时间均加1天
    public String EndDateAdd(String EndTime){
   
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String returnDate = null;
        try {
   
            Date EndDate = format.parse(EndTime);
            Calendar c = Calendar.getInstance();
            c.setTime(EndDate);
            c.add(Calendar.DAY_OF_MONTH,1);
            EndDate = c.getTime();
            returnDate = format.format(EndDate);
        } catch (ParseException e) {
   
            e.printStackTrace();
        }
        return returnDate;
    }

将前段传过来的查询条件,封装为一个es的查询语句

  

@Override
    public EsPeopleResult queryResultPeople(EsQueryPeople esQueryPeople) {
   
        try {
   
// 封装为查询语句
            String query = makeSearch(esQueryPeople);
        } catch (IllegalAccessException e) {
   
            e.printStackTrace();
        }


        return null;
    }

以上的代码query 就是makeSearch()函数返回的es的查询语句,那么这个函数里面是如何处理前段传过来的查询数据,并且返回给查询语句的呢?

这个makeSearch()函数里面的代码是:


private String makeSearch(EsQueryPeople esQueryPeople)
     throws IllegalAccessException {
   
       
 // 创建查询bulid,es的查询语句就是这个对象,
 //我们只需要把要查询的东西放到这个对象里面就可以了

SearchSourceBuilder searchSourceBuilder = 
new SearchSourceBuilder();

//编辑Es查询条件,因为前段可能传过来很多的查询条件,有的是根据时间段查询
//有的是精准查询,有的是模糊查询
//我们需要把这么多条件的查询连接起来,因为字段太多,我们重新写一个方法
BoolQueryBuilder boolQueryBuilder = editParams(esQueryPeople);


//解决Es7 以上版本最多只返回10000条数据问题
//将多个查询条件放到searchSourceBuilder对象里面
 searchSourceBuilder.query(boolQueryBuilder);
 
// 设置分页,根据前段传过来的分页参数,计算出从第几页开始查询
int form = (esQueryPeople.getPageNo() - 1) * esQueryPeople.getPageSize();

//searchSourceBuilder对象里面从第几页开始查询
searchSourceBuilder.from(form);
//searchSourceBuilder对象里面 共查询几条数据
searchSourceBuilder.size(esQueryPeople.getPageSize());

 // 设置按照热度,获取前段传过来的要根据哪个字段进行排序
String orderFiled = esQueryPeople.getOrderFiled();

//如果前段没有传,用默认的字段进行排序
if (StringUtils.isBlank(orderFiled)) {
   
            orderFiled = "data";
}
//获取前段传过来的排序类型,升序还是降序
String orderType = esQueryPeople.getOrderType();
//如果没有传,用默认的
if (StringUtils.isBlank(orderType)) {
   
            orderType = "desc";
}
// searchSourceBuilder对象里面的排序方法sort()
searchSourceBuilder.sort(orderFiled,
SortOrder.fromString(orderType));

//设置完成,将searchSourceBuilder对象转为字符串返回
String query = searchSourceBuilder.toString();


//searchSourceBuilder对象里面放了查询的相关的语句
return query;
    }
    /** * 编辑Es 查询条件 * * * @param paramVo */
    private BoolQueryBuilder editParams(EsQueryPeople paramVo) throws IllegalAccessException {
   
        // 基础查询
        BoolQueryBuilder mhxjccx = QueryBuilders.boolQuery();

        //查询处理
        if (null != paramVo) {
   

            //时间
            if (null != paramVo.getDatakssj() && !"".equals(paramVo.getDatakssj())) {
   
                if (null != paramVo.getDatajssj() && !"".equals(paramVo.getDatajssj())) {
   
                    RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("data").gte(paramVo.getDatakssj()).lte(EndDateAdd(paramVo.getDatajssj()));
                    mhxjccx.must(rangeQueryBuilder);
                } else {
   
                    RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("data").gte(paramVo.getDatakssj());
                    mhxjccx.must(rangeQueryBuilder);
                }
            } else if (null != paramVo.getDatajssj() && !"".equals(paramVo.getDatajssj())) {
   
                RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("data").lte(EndDateAdd(paramVo.getDatajssj()));
                mhxjccx.must(rangeQueryBuilder);
            }

// 姓名模糊查询
            if (paramVo.getName() != null && !paramVo.getName().isEmpty()) {
   
                WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery("name", "*" + paramVo.getName() + "*");
                mhxjccx.must(wildcardQueryBuilder);
            }
// 手机号码精确查询
            if (paramVo.getPhone() != null && !paramVo.getPhone().isEmpty()) {
   
                TermsQueryBuilder termQueryBuilder = QueryBuilders.termsQuery("phone", paramVo.getPhone());
                mhxjccx.must(termQueryBuilder);
            }

        }
        return mhxjccx;
    }

执行es查询条件的语句

已经将前段传过来的查询的条件封装为一个es查询的语句了,现在要执行这个语句了



这个是依赖里面的,直接拿过来用就可以
    @Autowired
    JestClient jestClient;
    @Value("${path}")
    private String path;

 @Override
    public EsPeopleResult queryResultPeople(EsQueryPeople esQueryPeople) {
   
        try {
   
// 封装为查询语句
            String query = makeSearch(esQueryPeople);
 // 进行查询,查询哪个索引库
            Search search = new Search.Builder(query).addIndex(path).build();
// 用这个 jestClient 依赖执行查询语句,返回查询结果 
            SearchResult searchResult = jestClient.execute(search);
        } catch (IllegalAccessException | IOException e) {
   
            e.printStackTrace();
        }


        return null;
    }

searchResult 这个返回的结果,就是查询出来的东西,但是我们要将查询出来的东西,格式化前段要的格式,也就是我们要整理一下查询出来的东西,再返回给前段

格式化查询的结果

我们将格式化结果的代码封装为一个方法

    /** * 格式化 结果 * * * @param paramVo */
    private EsPeopleResult makeResult(EsQueryPeople paramVo, SearchResult searchResult) {
   

        EsPeopleResult esMhcrgResult = new EsPeopleResult();
        List<EsQueryPeople> MhxxEsVoList = new ArrayList<>(paramVo.getPageSize());

        //获取sku列表
        List<SearchResult.Hit<EsQueryPeople, Void>> hits = searchResult.getHits(EsQueryPeople.class);
        for (SearchResult.Hit<EsQueryPeople, Void> hit : hits) {
   
// 获取实体类对象
            EsQueryPeople source = hit.source;
            MhxxEsVoList.add(source);
        }


        esMhcrgResult.setPeoplelist(MhxxEsVoList);
        // 获取总数(原来的)searchResult.getTotal() 报异常
        Long total = searchResult.getJsonObject().getAsJsonObject("hits")
                .get("total").getAsLong();
        esMhcrgResult.setTotal(total);
        //取记录个数并计算出总页数
        long totalPage = (total + paramVo.getPageSize() - 1) / paramVo.getPageSize();
        esMhcrgResult.setTotalPages(totalPage);
        return esMhcrgResult;

    }

业务层直接调用这个进行格式化查询出来的结果


    @Override
    public EsPeopleResult queryResultPeople(EsQueryPeople esQueryPeople) {
   
        EsPeopleResult esPeopleResult=null;
        try {
   
// 封装为查询语句
            String query = makeSearch(esQueryPeople);
 // 进行查询,查询哪个索引库
            Search search = new Search.Builder(query).addIndex(path).build();
// 用这个 jestClient 依赖执行查询语句,返回查询结果
            SearchResult searchResult = jestClient.execute(search);

// 格式化结果
            esPeopleResult = makeResult(esQueryPeople, searchResult);
        } catch (IllegalAccessException | IOException e) {
   
            e.printStackTrace();
        }


        return esPeopleResult;
    }

整个业务层的代码

package com.jing.elachsearch.service.impl;

import com.jing.elachsearch.pojo.EsPeopleResult;
import com.jing.elachsearch.pojo.EsQueryPeople;
import com.jing.elachsearch.service.EsMhcxService;
import io.searchbox.client.JestClient;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import io.searchbox.strings.StringUtils;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/** * @author * @date 202 */
@Service
public class EsMhcxServiceImpl  implements EsMhcxService {
   


    @Autowired
    JestClient jestClient;
    @Value("${path}")
    private String path;

    // 结束时间均加1天
    public String EndDateAdd(String EndTime){
   
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String returnDate = null;
        try {
   
            Date EndDate = format.parse(EndTime);
            Calendar c = Calendar.getInstance();
            c.setTime(EndDate);
            c.add(Calendar.DAY_OF_MONTH,1);
            EndDate = c.getTime();
            returnDate = format.format(EndDate);
        } catch (ParseException e) {
   
            e.printStackTrace();
        }
        return returnDate;
    }



    @Override
    public EsPeopleResult queryResultPeople(EsQueryPeople esQueryPeople) {
   
        EsPeopleResult esPeopleResult=null;
        try {
   
// 封装为查询语句
            String query = makeSearch(esQueryPeople);
 // 进行查询,查询哪个索引库
            Search search = new Search.Builder(query).addIndex(path).build();
// 用这个 jestClient 依赖执行查询语句,返回查询结果
            SearchResult searchResult = jestClient.execute(search);

// 格式化结果
            esPeopleResult = makeResult(esQueryPeople, searchResult);
        } catch (IllegalAccessException | IOException e) {
   
            e.printStackTrace();
        }


        return esPeopleResult;
    }


    private String makeSearch(EsQueryPeople esQueryPeople) throws IllegalAccessException {
   
        // 创建查询bulid
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //编辑Es查询条件
        BoolQueryBuilder boolQueryBuilder = editParams(esQueryPeople);
        //解决Es7 以上版本最多只返回10000条数据问题
        searchSourceBuilder.query(boolQueryBuilder);
        // 设置分页
        int form = (esQueryPeople.getPageNo() - 1) * esQueryPeople.getPageSize();
        searchSourceBuilder.from(form);
        searchSourceBuilder.size(esQueryPeople.getPageSize());
        // 设置按照热度
        String orderFiled = esQueryPeople.getOrderFiled();
        if (StringUtils.isBlank(orderFiled)) {
   
            orderFiled = "data";
        }
        String orderType = esQueryPeople.getOrderType();
        if (StringUtils.isBlank(orderType)) {
   
            orderType = "desc";
        }
        System.out.println("查询条件"+boolQueryBuilder);
        System.out.println("searchSourceBuilder:"+searchSourceBuilder);
        searchSourceBuilder.sort(orderFiled, SortOrder.fromString(orderType));
        String query = searchSourceBuilder.toString();

        return query;
    }




    /** * 编辑Es 查询条件 * * * @param paramVo */
    private BoolQueryBuilder editParams(EsQueryPeople paramVo) throws IllegalAccessException {
   
        // 基础查询
        BoolQueryBuilder mhxjccx = QueryBuilders.boolQuery();

        //查询处理
        if (null != paramVo) {
   

            //时间
            if (null != paramVo.getDatakssj() && !"".equals(paramVo.getDatakssj())) {
   
                if (null != paramVo.getDatajssj() && !"".equals(paramVo.getDatajssj())) {
   
                    RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("data").gte(paramVo.getDatakssj()).lte(EndDateAdd(paramVo.getDatajssj()));
                    mhxjccx.must(rangeQueryBuilder);
                } else {
   
                    RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("data").gte(paramVo.getDatakssj());
                    mhxjccx.must(rangeQueryBuilder);
                }
            } else if (null != paramVo.getDatajssj() && !"".equals(paramVo.getDatajssj())) {
   
                RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("data").lte(EndDateAdd(paramVo.getDatajssj()));
                mhxjccx.must(rangeQueryBuilder);
            }

// 姓名模糊查询
            if (paramVo.getName() != null && !paramVo.getName().isEmpty()) {
   
                WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery("name", "*" + paramVo.getName() + "*");
                mhxjccx.must(wildcardQueryBuilder);
            }
// 手机号码精确查询
            if (paramVo.getPhone() != null && !paramVo.getPhone().isEmpty()) {
   
                TermsQueryBuilder termQueryBuilder = QueryBuilders.termsQuery("phone", paramVo.getPhone());
                mhxjccx.must(termQueryBuilder);
            }

        }
        return mhxjccx;
    }



    /** * 格式化 结果 * * * @param paramVo */
    private EsPeopleResult makeResult(EsQueryPeople paramVo, SearchResult searchResult) {
   

        EsPeopleResult esMhcrgResult = new EsPeopleResult();
        List<EsQueryPeople> MhxxEsVoList = new ArrayList<>(paramVo.getPageSize());

        //获取sku列表
        List<SearchResult.Hit<EsQueryPeople, Void>> hits = searchResult.getHits(EsQueryPeople.class);
        for (SearchResult.Hit<EsQueryPeople, Void> hit : hits) {
   
// 获取实体类对象
            EsQueryPeople source = hit.source;
            MhxxEsVoList.add(source);
        }


        esMhcrgResult.setPeoplelist(MhxxEsVoList);
        // 获取总数(原来的)searchResult.getTotal() 报异常
        Long total = searchResult.getJsonObject().getAsJsonObject("hits")
                .get("total").getAsLong();
        esMhcrgResult.setTotal(total);
        //取记录个数并计算出总页数
        long totalPage = (total + paramVo.getPageSize() - 1) / paramVo.getPageSize();
        esMhcrgResult.setTotalPages(totalPage);
        return esMhcrgResult;

    }

}