ElasticSearch框架整合与使用

ElasticSearch框架整合与使用

以SpringBoot集成为例

ElasticSearch 是一种流行的企业级搜索引擎,是一个分布式,高性能、高可用、可伸缩的搜索和分析系统。

通俗点来说,它就是提供一个存储数据的地方,然后搜索起来很快,特别是联想搜索,也就是模糊查询这种。

该篇包含内容:

1.基于windows ,下载安装 ElasticSearch(可以理解为一直存取数据的平台);

2.创建Springboot,整合ElasticSearch,使用入门的一些简单操作(插入,查询数据等)。

进入正题,

ElasticSearch 我使用版本为: 7.8.0

Springboot 我使用版本为:2.2.13.RELEASE

记住版本非常重要
重申一遍版本非常重要!!!!

第一步
首先是ElasticSearch 7.8.0版本下载安装,

可以到官网自行下载,也可以点击链接下载

ElasticSearch 7.8.0 baidu网盘下载链接:

链接:https://pan.baidu.com/s/1XBPFOQ4-pE-oojvGY1vDkg
提取码:47is

下载完解压,然后进到bin目录,运行elasticsearch.bat 即可。

运行后:在这里插入图片描述

第二步
开始创建springboot项目,

创建完后,记得把springboot版本改成2.X版本,这里我使用的是2.2.13 RELEASE
在这里插入图片描述
然后是在pom.xml文件加入需要用到的依赖包,

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

然后是application.yml 文件:

spring:
 data:
  elasticsearch:
    cluster-nodes: 127.0.0.1:9300
server:
  port: 8066

创建一个Blog.class 类,用于测试例子的数据的存取:

注意 这里的@Document(indexName = “testdata”, type = “blogs”)

indexName 索引名称,其实相当于咱们的数据库名称 ,必须为小写, 不然会报org.elasticsearch.indices.InvalidIndexNameException异常

而type:类型 ,其实相当于咱们的数据库表的名称

import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Document;
 
/**
 **/
@Data
@Document(indexName = "testdata", type = "blogs")
public class Blog {
 
    private Long id;
    private String masterName;
    private Integer articleNum;
    private Integer commentNum;
    private Integer thumbNum;
    private String description;
 
}

接着创建一个DataTestController.class,写一些测试的接口:

import com.example.elastucsearchdemo.pojo.Blog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
 
/**
 *
 **/
@RestController
public class DataTestController {
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
 
    @GetMapping("/addTest")
    public String testElSearch() {
        //该list用于添加需要存入的数据
        List<IndexQuery> indexQueryList = new ArrayList<>();
 
        //模拟一些数据
 
        Blog blog = new Blog();
        blog.setId((long) new Random().nextInt(1500));
        blog.setMasterName("JCccc");
        blog.setArticleNum(10);
        blog.setCommentNum(29);
        blog.setThumbNum(100);
        blog.setDescription("分享不仅为了别人,也是为了自己");
 
        //把这个数据放入indexQueryList
        indexQueryList.add(new IndexQueryBuilder().withObject(blog).build());
 
        //循环模拟一些数据
        for (int i = 1; i <= 6; i++) {
 
            Blog blog2 = new Blog();
            blog2.setId((long) new Random().nextInt(1500));
            blog2.setMasterName("Test");
            blog2.setArticleNum(i*60);
            blog2.setCommentNum(i*16);
            blog2.setThumbNum(i*500);
            blog2.setDescription("测试添加"+i);
            indexQueryList.add(new IndexQueryBuilder().withObject(blog2).build());
        }
        elasticsearchTemplate.bulkIndex(indexQueryList);
        return  "add success ";
 
}
}

运行项目,调用一下这个插入数据的模拟接口:
在这里插入图片描述
添加完毕了,但是到底是否真的添加进去了呢? 接下来暂时使用 elasticsearchTemplate提供的查询方法来验证下

写个查询接口:

@GetMapping("/getTestData")
    public  List<Blog> getTestData(){
        
        
        //精确查询
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchPhraseQuery("masterName", "JCccc"))
                .build();
        List<Blog> list = elasticsearchTemplate.queryForList(searchQuery, Blog.class);
        return list;
    }

调用下接口看下,查询正常:

在这里插入图片描述
那么接下来我们来增加多一些数据,进行模糊查询

//该list用于添加需要存入的数据
        List<IndexQuery> indexQueryList = new ArrayList<>();
 
        //循环模拟一些数据
        for (int i = 1; i <= 3; i++) {
 
            Blog blog2 = new Blog();
            blog2.setId((long) new Random().nextInt(1500));
            blog2.setMasterName("Test"+i*2*3);
            blog2.setArticleNum(i*60);
            blog2.setCommentNum(i*16);
            blog2.setThumbNum(i*500);
            blog2.setDescription("测试添加"+i);
            indexQueryList.add(new IndexQueryBuilder().withObject(blog2).build());
        }
        elasticsearchTemplate.bulkIndex(indexQueryList);

然后在验证下这个模糊搜索:

@GetMapping("/queryTestData")
    public  List<Blog> getTestData(){
 
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.wildcardQuery("masterName", ("*" + "Test" + "*").toLowerCase()))
                .build();
        List<Blog> list = elasticsearchTemplate.queryForList(searchQuery, Blog.class);
 
        return  list;
    }

再调用一下,就可以看到模糊查询出所有包含Test的数据了。
在这里插入图片描述
那么假设已经知道了id,单个数据查询又是如何操作呢?如下,单个根据id查询,

 @GetMapping("/queryTestDataOne")
    public  String queryTestDataOne(){
 
        GetQuery query = new GetQuery();
        query.setId("114");
 
        Blog blog = elasticsearchTemplate.queryForObject(query, Blog.class);
       return blog.toString();
    }

在这里插入图片描述
那么假如我们不知道主键id,我们只知道一些条件,例如想查询 点赞数 thumbNum =1000的 数据,

也就是单条件查询:

这时候我们需要实现自定义查询类ElasticsearchOptionSearchRepository.class

import com.example.elastucsearchdemo.pojo.Blog;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
 
/**
 *
 **/
@Repository
public interface ElasticsearchOptionSearchRepository extends ElasticsearchRepository<Blog,String> {
 
}

然后写个接口:

@Autowired
    private ElasticsearchOptionSearchRepository elasticsearchOptionSearchRepository;
 
 
    //根据单条件查询
    @GetMapping("/queryTestDataCondition")
    public  List queryTestDataCondition(){
 
        List<Blog> list = new ArrayList<>();
        TermQueryBuilder termQuery = new TermQueryBuilder("thumbNum", 1000);
        Iterable<Blog> iterable = elasticsearchOptionSearchRepository.search(termQuery);
        iterable.forEach(e -> list.add(e));
 
        return list;
 
    }

运行调用接口,查看情况,都查询出来了:
在这里插入图片描述
第三步
其实到此咱们对于springboot 整合 elasticsearch 已经基本掌握了, 但是光这么插入数据查询数据,还是比较空洞,不免初学者会感觉这跟存缓存差不多,不知道数据到底有没有真正存入。

所以,我们最后一步是,安装使用可视化客户端 ElasticHD 。

依旧,不需要继续在网上找安装包了,我这边提供给大家的windows版本 5.6.0 :

ElasticHD 5.6.0 baidu网盘下载链接:

https://pan.baidu.com/s/1pGPPB9IU6GtXuvaX-B5mdg
提取码: epgp
1.下载安装解压,如:
在这里插入图片描述

  1. 不要双击运行记住! 进入到解压的目录下,通过命令执行,如:
    在这里插入图片描述

3.运行成功后,会直接弹出ElasticHD的可视化页面 ,如:
在这里插入图片描述

然后咱们可以查看到我们上面的测试插入的数据:

在这里插入图片描述

选择我们刚刚存入数据的index(类似数据库名):
在这里插入图片描述
点击搜索即可看到数据:
在这里插入图片描述
PS:整合部分为网上转载,为了方便快速集成进行练习。

进阶用法:多条件查询

多条件查询以ElasticSearch 中boolQueryBuilder的使用为例:

首先了解bool 查询的各个用法
Bool查询对应Lucene中的BooleanQuery,它由一个或者多个子句组成,每个子句都有特定的类型

◆ must
返回的文档必须满足must子句的条件,并且参与计算分值

◆ filter
返回的文档必须满足filter子句的条件,但是不会像must一样,参与计算分值

◆ should
返回的文档可能满足should子句的条件.在一个bool查询中,如果没有must或者filter,有一个或者多个should子句,那么只要满足一个就可以返回.minimum_should_match参数定义了至少满足几个子句.

◆ must_not
返回的文档必须不满足定义的条件

如果一个查询既有filter又有should,那么至少包含一个should子句.
bool查询也支持禁用协同计分选项disable_coord.一般计算分值的因素取决于所有的查询条件.

bool查询也是采用more_matches_is_better的机制,因此满足must和should子句的文档将会合并起来计算分值.

代码样例:

public void () throws IOException {
    SearchRequest searchRequest = new SearchRequest("item");
    // 构建查询的请求体
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    
    boolQueryBuilder.must(QueryBuilders.matchQuery("scompCode", "G0000001"));
    // 模糊查询
    boolQueryBuilder.filter(QueryBuilders.wildcardQuery("itemDesc", "手机"));
    // 范围查询 from:相当于闭区间; gt:相当于开区间(>) gte:相当于闭区间 (>=) lt:开区间(<) lte:闭区间 (<=)
    boolQueryBuilder.filter(QueryBuilders.rangeQuery("itemPrice").from(4500).to(8899));
    sourceBuilder.query(boolQueryBuilder);

    searchRequest.source(sourceBuilder);
    SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
    logger.info("查询数据:{}", Arrays.toString(searchResponse.getHits().getHits()));
}

进行了上述简单介绍后,我们举出几个场景,结合场景需求进行更加深入的理解。

业务场景一:

  用户想对专家信息进行查询,希望有这样两个搜索框,第一个搜索框可以在姓名、性别、公司中进行全局搜索,第二个搜索框希望在电话、职位、简介中进行全局搜索。

主要代码:

// 构建查询的请求体
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//搜索框一
//query.getData为搜索框输入的值,"name","sex","company"为索引的字段名
       boolQueryBuilder.should(QueryBuilders.multiMatchQuery(query.getData(),"name","sex","company" ));
//搜索框二
//query.getData2为搜索框输入的值,"phone","position","introduction"为索引的字段名
       boolQueryBuilder.should(QueryBuilders.multiMatchQuery(query.getData2(),"phone","position","introduction" ));
       sourceBuilder.query(boolQueryBuilder);
       request.source(sourceBuilder);
       System.out.println(request);
       SearchResponse response = client.search(request, RequestOptions.DEFAULT);
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值