Springboot对Elasticsearch的CRUD

碰到一点压力就把自己变成不堪重负的样子,碰到一点不确定性就把前途描绘成黯淡无光的样子,碰到一点不开心就把它搞得似乎是自己这辈子最黑暗的时候。

  我们安装了Elasticsearch并且学会了它的各种查询,终归是要在项目中使用它。所以今天就创建一个项目,看一看Springboot是如何使用它的。
该项目代码放在:https://gitee.com/siumu/blog_code.git

准备工作

  首先我们需要创建一个Springboot项目,非常的简单,也不需要什么额外的jar包,只需要把spring-boot-starter-data-elasticsearch引入进来就可以了。我们如果了解过的话可能就知道,需要用Java High Level REST Client来对Elasticsearch进行操作,但是springboot很人性化的帮我们集成了这个东西,还封装了一下,让我们更加的容易使用。然后你还需要准备一个可以访问的Elasticsearch服务

pom文件
<dependency>
  <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-json</artifactId>
    <version>5.2.4</version>
</dependency>
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-core</artifactId>
    <version>5.2.4</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

  这里还有一个问题就是版本问题,我创建的springboot版本是2.3.5,它默认使用的Java High Level REST Client是7.6.2,但是我们的Elasticsearch是7.9.2,为了让他版本一致,我们只需要在POM文件中写上elasticsearch的版本就可以了
在这里插入图片描述

配置文件
spring:
  elasticsearch:
    rest:
      uris:
        - http://192.168.36.215:9200

  写上你启动的Elasticsearch服务的地址,如此一来我们的准备工作就做完了,当然还要有数据,我们就用上篇博客的数据吧,方便点。有了数据,接下来的操作就很简单了,整一个实体类,然后使用spring-boot-starter-data-elasticsearch调用CRUD就可以了。

上手操作

  建实体类:

/**
 * @author xiumu
 * @version 1.0
 * @date 2020/11/7 19:12
 */
@Data
@Document(indexName = "xiumu_user")
public class UserInfo {

    @Id
    private String id;
    /**
     * 姓名
     */
    private String username;
    /**
     * 年龄
     */
    private Integer age;
    /**
     * 性别
     */
    private Character gender;
    /**
     * 个性签名
     */
    private String description;
}

这代码很简单吧,就像我们写实体类跟数据库映射一样,一模一样的操作。然后我们就像使用Jpa似的,创建一个repository

/**
 * @author xiumu
 * @version 1.0
 * @date 2020/11/8 15:09
 */
@Repository
public interface UserInfoRepository extends ElasticsearchRepository<UserInfo, String> {
}

这样我们就可以使用它来进行简单的CRUD了。接下来我们就在测试类里边来使用。

@SpringBootTest
class SearchApplicationTests {

    @Autowired
    private UserInfoRepository userInfoRepository;


    @Test
    void contextLoads() {
        Iterable<UserInfo> userInfos = userInfoRepository.findAll();
        userInfos.forEach(System.out::println);
    }
}

我们看到,它会给我们返回一个Iterable对象。而不是我们经常见到的List对象。测试结果如下:
在这里插入图片描述
虽然它默认给我们返回Iterable对象,但是如果我们想要它给我们返回List对象也是可以的,就像这样:

/**
 * @author xiumu
 * @version 1.0
 * @date 2020/11/8 15:09
 */
@Repository
public interface UserInfoRepository extends ElasticsearchRepository<UserInfo, String> {

    @Override
    List<UserInfo> findAll();
}

我们直接把它给覆盖掉,这样再使用List来接收是完全没有问题的。
在这里插入图片描述
我们调用的时候发现其实它已经实现了很多方法:
在这里插入图片描述
然后我们要是根据字段来查询也是很方便,或者分页查询是非常的方便,就跟使用Jpa操作数据库一样方便。

/**
 * @author xiumu
 * @version 1.0
 * @date 2020/11/8 15:09
 */
@Repository
public interface UserInfoRepository extends ElasticsearchRepository<UserInfo, String> {

    @Override
    List<UserInfo> findAll();
    //根据名字查找
    List<UserInfo> findByUsername(String username);
    //根据年龄查找
    List<UserInfo> findByAge(Integer age);
    //根据名字或者个性签名查找
    List<UserInfo> findByUsernameOrDescription(String username, String description);
    //分页查询
    @Override
    Page<UserInfo> findAll(Pageable pageable);
    //根据名字分页查询
    Page<UserInfo> findByUsername(String username,Pageable pageable);
}

然后我们在测试类里边进行测试

@Test
void contextLoads() {
     List<UserInfo> userInfos = userInfoRepository.findAll();
     userInfos.forEach(System.out::println);
     System.out.println("-------------------------------------");
     userInfos = userInfoRepository.findByAge(20);
     userInfos.forEach(System.out::println);
     System.out.println("-------------------------------------");
     userInfos = userInfoRepository.findByUsername("射手");
     userInfos.forEach(System.out::println);
     System.out.println("-------------------------------------");
     userInfos = userInfoRepository.findByUsernameOrDescription("赵信","风一样的男人");
     userInfos.forEach(System.out::println);
     System.out.println("-------------------------------------");
     Page<UserInfo> userInfos1 = userInfoRepository.findAll(PageRequest.of(0,5));
     userInfos1.forEach(System.out::println);

 }

测试结果如下:
在这里插入图片描述
需要注意的是分页查询要从第0页开始查起
除了这些还有很多查询方法,我们可以看它的官方文档,还是挺详细的。
在这里插入图片描述

ElasticsearchRestTemplate查询

  有时候上边那个查询满足不了我们的需求,我们想要它返回更多原生的东西,也要自定义很多东西,那么我们就需要用到这个ElasticsearchRestTemplate查询了,这个东西能做更多的事情,也方便我们自定义一些查询操作。它用起来也非常的方便,我们只需要在用到它的类中将它注入进来即可。

 @Autowired
 private ElasticsearchRestTemplate elasticsearchRestTemplate;

那么我们就在测试类里直接使用。它同样封装了很多方法,我们先来看它的第一个查询方法
在这里插入图片描述
  我们来看它的参数,Query,Class,IndexCoordinates,这不是一看就知道,Query就是查询条件嘛,Class应该就是返回对象的类型,IndexCoordinates就是索引呗。

IndexCoordinates类

  我们先看这个IndexCoordinates类,直接看源码,这里构造函数被私有化,想要生成这个类的对象,就得调用这个of方法,把索引名字传进去,默认的type是"_doc"。而这个of方法可以传一个或者多个索引名称,岂不就是对应上了我们上个博客讲的多索引查询。
在这里插入图片描述

Query接口

  接下来我们看这个查询条件Query接口,它有好几个实现类,理论上来说我们只需要用NativeSearchQuery这个实现类就可以了,基本上你想要的的查询条件它都能生成。我们先看这个类的源码
在这里插入图片描述
  一看它的构造器源码和参数,以及参数名称我们就立马知道,必然是使用了Builder设计模式,不知道大家有没有听说过这个建造者设计模式。这个呢先不管,我们还是直接说怎么生成查询条件吧。我们发现要想生成一个NativeSearchQuery的对象,必须要有QueryBuilder这个条件构造器
QueryBuilder对象
  既然这个QueryBuilder是必须的,那我们就看看这个接口是什么东西吧。首先进入源码,看看它的实现类有哪些
在这里插入图片描述
  我们看到它有很多实现类,我就找了这么几个我们常用的,看起来是不是很熟悉,就是构建我们经常使用的match查询,query_string查询,range查询等等。每一种查询都被封装成类。当然,我们想要构建各种查询条件不能这么直接new这些对象,代码看起来不好看。所以它很方便的给我们提供了一个构建这些条件构造器的类QueryBuilders。它就能帮我们创建这些对象。

开始使用

那么我们直接开始使用吧,眼睛见到的才会更直观。

@Test
void testElasticsearchRestTemplateDemo() {
     //要查询的索引
     IndexCoordinates xiumuUser = IndexCoordinates.of("xiumu_user");

     //构建查询条件,查询全部
     QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
     Query query = new NativeSearchQuery(queryBuilder);
     //执行查询
     SearchHits<UserInfo> userInfoSearchHits = elasticsearchRestTemplate.search(query, UserInfo.class, xiumuUser);
     //打印查询结果
     for (SearchHit<UserInfo> searchHit : userInfoSearchHits.getSearchHits()) {
         System.out.println(searchHit.getContent());
     }
 }

执行结果如下:
在这里插入图片描述
如图所示,确实查到了结果。我们看到,查询结果的返回类型是SearchHits,有没有一点熟悉的名字,我们用kibana查询结果不也是叫hits吗:
在这里插入图片描述
SearchHits是一个接口,我们来看它的实现类里面的属性:
在这里插入图片描述
这不就跟我们用kibana查询的结果对应上了。到了这里我们基本已经知道了如何使用它,更加高级的功能还需要我们慢慢的摸索。

更复杂的查询

我们需要更加复杂的查询怎么构建呢?以下就是一些常用的查询方式:

 //match查询age是20的条件
 QueryBuilders.matchQuery("age",20);
 
 //term查询age是20的条件
 QueryBuilders.termQuery("age",20);
 
 //terms查询age是20或者200,或者50的条件
 QueryBuilders.termsQuery("age",20,200,50);
 
 //query_string全文检索“xiumu”
 QueryBuilders.queryStringQuery("xiumu");
 
 //query_string检索username是“xiumu”
 QueryBuilders.queryStringQuery("xiumu").field("username");
 
 //multi_match查询字段username或者description的值是xiumu
 QueryBuilders.multiMatchQuery("xiumu","username","description");
 
 //range查询字段age的范围是在[18-200]之间
 QueryBuilders.rangeQuery("age").gte(18).lte(200);
 
 //exits查询字段age有值
 QueryBuilders.existsQuery("age");
 
 //wildcard查询字段description是以“男人”结尾的
 QueryBuilders.wildcardQuery("description","*男人");
 
 //bool查询
 BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
 //bool查询里添加must多个条件
 boolQueryBuilder.must(QueryBuilders.termQuery("age",20));
 boolQueryBuilder.must(QueryBuilders.existsQuery("age"));
 boolQueryBuilder.must(QueryBuilders.wildcardQuery("description","*男人"));
 
 //等等各种查询.......

结尾

  Springboot操作Elasticsearch我们就这样简简单单的学会了,当然这是个刚刚入门到的基础,还有很多更复杂的操作需要摸索。
相关代码放在:https://gitee.com/siumu/blog_code.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值