SpringBoot整合elasticsearch

SpringBoot整合ES

1.pom.xml依赖

<!--引入es的坐标-->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>7.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>7.4.0</version>
        </dependency>

2.application.yml配置

server:
  port: 8080

elasticsearch:
  host: localhost
  port: 9200

3.ESConfig.java

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConfigurationProperties(prefix="elasticsearch")
public class ElasticSearchConfig {

    private String host;

    private int port;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }
    @Bean
    public RestHighLevelClient client(){
        return new RestHighLevelClient(RestClient.builder(
                new HttpHost(host,port,"http")
        ));
    }
}

4.测试

4.1索引测试

数据准备

import lombok.Data;

@Data
public class Person {
    private String id;
    private String name;
    private int age;
    private String address;
}
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.IndicesClient;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.IOException;
import java.util.Map;

@SpringBootTest(classes = ESAPP.class)
@RunWith(SpringRunner.class)
public class ESTest {
    @Autowired
    private RestHighLevelClient client;

    @Test
    //添加索引
    public void addIndex()throws Exception{
        //1.使用client获取操作索引的对象
        IndicesClient indices = client.indices();
        //2.具体操作,获取返回值
        CreateIndexRequest createIndexRequest=new CreateIndexRequest("ztuo");
        CreateIndexResponse response = indices.create(createIndexRequest, RequestOptions.DEFAULT);
        //3.根据返回值判断结果
        System.out.println(response.isAcknowledged());
    }

    /**
     * 添加索引,并添加映射
     */
    @Test
    public void addIndexAndMapping() throws IOException {
        //1.使用client获取操作索引对象
        IndicesClient indices = client.indices();
        //2.具体操作获取返回值
        //2.具体操作,获取返回值
        CreateIndexRequest createIndexRequest = new CreateIndexRequest("itcast");
        //2.1 设置mappings
        String mapping = "{\n" +
                "      \"properties\" : {\n" +
                "        \"address\" : {\n" +
                "          \"type\" : \"text\",\n" +
                "          \"analyzer\" : \"ik_max_word\"\n" +
                "        },\n" +
                "        \"age\" : {\n" +
                "          \"type\" : \"long\"\n" +
                "        },\n" +
                "        \"name\" : {\n" +
                "          \"type\" : \"keyword\"\n" +
                "        }\n" +
                "      }\n" +
                "    }";
        createIndexRequest.mapping(mapping, XContentType.JSON);

        CreateIndexResponse createIndexResponse = indices.create(createIndexRequest, RequestOptions.DEFAULT);
        //3.根据返回值判断结果
        System.out.println(createIndexResponse.isAcknowledged());
    }


    /**
     * 查询索引
     */
    @Test
    public void queryIndex() throws Exception{
        IndicesClient indices = client.indices();

        GetIndexRequest getIndexRequest=new GetIndexRequest("itcast");
        GetIndexResponse response = indices.get(getIndexRequest, RequestOptions.DEFAULT);
        Map<String, MappingMetaData> mappings=response.getMappings();
        //iter 提示foreach
        for (String key : mappings.keySet()) {
            System.out.println(key+"==="+mappings.get(key).getSourceAsMap());
        }
    }

    /**
     * 删除索引
     */
    @Test
    public void deleteIndex() throws IOException {
        IndicesClient indices = client.indices();
        DeleteIndexRequest deleteRequest=new DeleteIndexRequest("itheima");
        AcknowledgedResponse delete = indices.delete(deleteRequest, RequestOptions.DEFAULT);
        System.out.println(delete.isAcknowledged());

    }

    /**
     * 索引是否存在
     */
    @Test
    public void existIndex() throws IOException {
        IndicesClient indices = client.indices();

        GetIndexRequest getIndexRequest=new GetIndexRequest("itheima");
        boolean exists = indices.exists(getIndexRequest, RequestOptions.DEFAULT);

        System.out.println(exists);
    }

}

4.2文档测试

import cn.ztuo.es.pojo.Person;
import com.alibaba.fastjson.JSON;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@SpringBootTest(classes = ESAPP.class)
@RunWith(SpringRunner.class)
public class ESdocTest {
    @Autowired
    private RestHighLevelClient client;

    /**
     * 添加文档,使用map作为数据
     */
    @Test
    public void addDoc()throws Exception{
        //数据对象,map
        Map data = new HashMap();
        data.put("address", "北京昌平");
        data.put("name", "大胖");
        data.put("age", 20);

        //1。获取操作文档对象
        IndexRequest request=new IndexRequest("itcast").id("1").source(data);
        IndexResponse response = client.index(request, RequestOptions.DEFAULT);

        //打印响应结果
        System.out.println(response.getId());
    }

    /**
     * 添加文档,使用对象作为数据
     * 修改文档:添加文档时,如果id存在则修改,id不存在则添加
     */
    @Test
    public void addDoc2() throws IOException {
        //数据对象,javaObject
        Person p = new Person();
        p.setId("2");
        p.setName("小胖2222");
        p.setAge(30);
        p.setAddress("陕西西安");

        //将对象转为json
        String data = JSON.toJSONString(p);

        //1.获取操作文档的对象
        IndexRequest request = new IndexRequest("itcast").id(p.getId()).source(data,
                XContentType.JSON);
        //添加数据,获取结果
        IndexResponse response = client.index(request, RequestOptions.DEFAULT);

        //打印响应结果
        System.out.println(response.getId());
    }

    /**
     * 根据id查询文档
     */
    @Test
    public void getDoc()throws Exception{
        GetRequest indexRequest=new GetRequest("itcast","2");
        GetResponse response = client.get(indexRequest, RequestOptions.DEFAULT);
        System.out.println(response.getSourceAsString());
    }
}

4.3-高级查询


import cn.ztuo.es.pojo.Goods;
import com.alibaba.fastjson.JSON;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@SpringBootTest(classes = ESAPP.class)
@RunWith(SpringRunner.class)
public class ESQueryTest {
    @Autowired
    private RestHighLevelClient client;

    /**
     * 批量导入
     */
    @Test
    public void imporyData()throws Exception{
        //1.查询所有数据,mysql
        //List<Goods> goodsList = goodsMapper.findAll();
        List<Goods> goodsList = new ArrayList<>();

        //2.bulk导入
        BulkRequest bulkRequest = new BulkRequest();

        //2.1 循环goodsList,创建IndexRequest添加数据
        for (Goods goods : goodsList) {
            //2.2 设置spec规格信息 Map的数据   specStr:{}
            //goods.setSpec(JSON.parseObject(goods.getSpecStr(),Map.class));

            String specStr = goods.getSpecStr();
            //将json格式字符串转为Map集合
            Map map = JSON.parseObject(specStr, Map.class);
            //设置spec map
            goods.setSpec(map);
            //将goods对象转换为json字符串
            String data = JSON.toJSONString(goods);//map --> {}
            IndexRequest indexRequest = new IndexRequest("goods");
            indexRequest.id(goods.getId() + "").source(data, XContentType.JSON);
            bulkRequest.add(indexRequest);
        }

        BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(response.status());
    }

    /**
     * 查询所有
     *  1. 高级查询
     *  2. 将查询结果封装为Goods对象,装载到List中
     *  3. 分页。默认显示10条
     */
    @Test
    public void queryPlusAll() throws Exception{
        //2. 构建查询请求对象,指定查询的索引名称
        SearchRequest searchRequest=new SearchRequest("goods");

        //3. 创建查询条件构建器SearchSourceBuilder
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();

        //  查询条件 match_all查询
        MatchAllQueryBuilder query = QueryBuilders.matchAllQuery();


        /*//term Query为精确查询,在搜索时会整体匹配关键字,不再将关键字分词。
        QueryBuilder query = QueryBuilders.termQuery("title", "华为");*/


        /*//match Query即全文检索,它的搜索方式是先将搜索字符串分词,再使用各各词条从索引中搜索。
        MatchQueryBuilder query = QueryBuilders.matchQuery("title", "华为手机");
        query.operator(Operator.AND);//求交集*/

        /*//模糊查询 wildcard:会对查询条件进行分词
        WildcardQueryBuilder query = QueryBuilders.wildcardQuery("title", "华*");//华后多个字符
        //正则查询
        RegexpQueryBuilder query = QueryBuilders.regexpQuery("title", "\\w+(.)*");
        //前缀查询
        PrefixQueryBuilder query = QueryBuilders.prefixQuery("brandName", "三");*/


        /*//范围查询 以price 价格为条件
        RangeQueryBuilder query = QueryBuilders.rangeQuery("price");
        //指定下限
        query.gte(2000);
        //指定上限
        query.lte(3000);*/


        /*//queryString
        QueryStringQueryBuilder query =
                QueryBuilders.queryStringQuery("华为手机")
                        .field("title").field("categoryName").field("brandName")
                        .defaultOperator(Operator.AND);*/


        /*//boolQuery:对多个查询条件连接。
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //2.构建各个查询条件
        //2.1 查询品牌名称为:华为
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("brandName", "华为");
        boolQuery.must(termQueryBuilder);

        //2.2. 查询标题包含:手机
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("title", "手机");
        boolQuery.filter(matchQuery);

        //2.3 查询价格在:2000-3000
        RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("price");
        rangeQuery.gte(2000);
        rangeQuery.lte(3000);
        boolQuery.filter(rangeQuery);*/


        //聚合查询 查询品牌列表  只展示前100条
        AggregationBuilder aggregation= AggregationBuilders.terms("goods_brands").field("brandName").size(100);
        sourceBuilder.aggregation(aggregation);


        /*//高亮查询
        // 1. 查询title包含手机的数据
        MatchQueryBuilder query = QueryBuilders.matchQuery("title", "手机");

        sourceBulider.query(query);

        //设置高亮
        HighlightBuilder highlighter = new HighlightBuilder();
        //设置三要素
        highlighter.field("title");
        //设置前后缀标签
        highlighter.preTags("<font color='red'>");
        highlighter.postTags("</font>");

        //加载已经设置好的高亮配置
        sourceBulider.highlighter(highlighter);*/



        //5.指定查询条件
        sourceBuilder.query(query);

        //6.添加查询条件构建器
        searchRequest.source(sourceBuilder);

        //7.添加分页信息
        sourceBuilder.from(0);
        sourceBuilder.size(100);

        //1. 查询,获取查询结果
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        //8.获取命中对象
        SearchHits hits = searchResponse.getHits();

        //8.1获取总记录条数
        long value = hits.getTotalHits().value;
        System.out.println("总数:"+value);

        //8.2获取hits数据 数组
        SearchHit[] hits1 = hits.getHits();
        //获取json字符串格式的数据
        List<Goods> goodsList =new ArrayList<>();
        for (SearchHit searchHit : hits1) {
            String sourceAsString = searchHit.getSourceAsString();
            //转为java对象
            Goods goods = JSON.parseObject(sourceAsString, Goods.class);
            goodsList.add(goods);
        }
        for (Goods goods : goodsList) {
            System.out.println(goods);
        }
    }
}

5.高级查询解释

5.1-matchAll-脚本

查询所有商品信息

默认查询只能查询10条数据

5.2-termQuery

term Query为精确查询,在搜索时会整体匹配关键字,不再将关键字分词。

5.3-matchQuery

match Query即全文检索,它的搜索方式是先将搜索字符串分词,再使用各各词条从索引中搜索。

5.4-termQuery和matchQuery的区别

  • term query会去倒排索引中寻找确切的term,它并不知道分词器的存在。这种查询适合keywordnumericdate
  • match query知道分词器的存在。并且理解是如何被分词的

5.5-模糊查询(了解)

wildcard查询:会对查询条件进行分词。还可以使用通配符 ?(任意单个字符) 和 * (0个或多个字符)

"*华*"  包含华字的
"华*"   华字后边多个字符
"华?"  华字后边单个字符
"*华"或"?华" 会引发全表(全索引)扫描 注意效率问题
# wildcard 查询。查询条件分词,模糊查询
GET goods/_search
{
  "query": {
    "wildcard": {
      "title": {
        "value": "华*"
      }
    }
  }
}
5.5.1-正则查询
\W:匹配包括下划线的任何单词字符,等价于 [A-Z a-z 0-9_]   开头的反斜杠是转义符

+号多次出现

(.)*为任意字符
正则查询取决于正则表达式的效率
GET goods/_search
{
  "query": {
    "regexp": {
      "title": "\\w+(.)*"
    }
  }
}
5.5.2-前缀查询

对keyword类型支持比较好

# 前缀查询 对keyword类型支持比较好
GET goods/_search
{
  "query": {
    "prefix": {
      "brandName": {
        "value": "三"
      }
    }
  }
}

5.6-范围&排序查询

范围查询:查找指定字段在指定范围内包含值:gte大于等于,lte 小于等于

gte: greater than or equal 大于等于
lte: less than or equal 小于等于
排序查询:desc 降序,asc升序

5.7-queryString多字段查询

queryString 多条件查询,可以让字符串中包含关键词

•会对查询条件进行分词。
•然后将分词后的查询条件和词条进行等值匹配
•默认取并集(OR)
•可以指定多个查询字段

query_string:识别query中的连接符(or 、and)

# queryString
GET goods/_search
{
  "query": {
    "query_string": {
      "fields": ["title","categoryName","brandName"], 
      "query": "华为 AND 手机"
    }
  }
}

simple_query_string:不识别query中的连接符(or 、and),查询时会将 “华为”、“and”、“手机”分别进行查询

GET goods/_search
{
  "query": {
    "simple_query_string": {
      "fields": ["title","categoryName","brandName"], 
      "query": "华为 AND 手机"
    }
  }
}

query_string:有default_operator连接符的脚本

GET goods/_search
{
  "query": {
    "query_string": {
      "fields": ["title","brandName","categoryName"],
      "query": "华为手机 "
      , "default_operator": "AND"
    }
  }
}

5.8-布尔查询-脚本

boolQuery:对多个查询条件连接。

must(and):条件必须成立
must_not(not):条件必须不成立
should(or):条件可以成立
filter:条件必须成立,性能比must高。不会计算得分
       得分:即条件匹配度,匹配度越高,得分越高

5.9-高亮查询-脚本

高亮显示可以将搜索结果一个或多个字突出显示,以便向用户展示匹配关键字的位置。

高亮三要素:

•高亮字段

•前缀

•后缀

默认前后缀 :

<em>手机</em>

替换默认高亮前后缀为:更改字体颜色为red

GET goods/_search
{
  "query": {
    "match": {
      "title": "电视"
    }
  },
  "highlight": {
    "fields": {
      "title": {
        "pre_tags": "<font color='red'>",
        "post_tags": "</font>"
      }
    }
  }
}
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值