6.5 Elasticsearch(五)Spring Data Elasticsearch - 增删改查API


文章目录

  • 1.Spring Data `Elasticsearch`
  • 2.案例准备
    • 2.1 在 Elasticsearch 中创建 students 索引
    • 2.2 案例测试说明
  • 3.创建项目
    • 3.1 新建工程
    • 3.2 新建 springboot module,添加 spring data elasticsearch 依赖
    • 3.3 pom.xml 文件
    • 3.4 application.yml 配置
  • 4.Student 实体类
  • 5.通过 ElasticsearchRepository 实现 CRUD 操作
    • 5.1 StudentRepository接口
    • 5.2 业务类 StudentService
    • 5.3 测试学生数据的 CRUD 操作
  • 6.使用 Repository 构建查询
    • 6.1 Repository 方法命名规范
    • 6.2 Repository API查询案例
    • 6.3 创建测试方法进行测试
  • 7.分页操作
    • 7.1 Pageable
    • 7.2 修改 StudentService
    • 7.3 在测试类中添加测试方法
  • 8.查询结果的高亮显示
    • 8.1 接口方法
    • 8.2 测试类方法
  • 9.使用 Criteria 构建查询
    • 9.1 StudentSearcher
    • 9.2 在测试类中测试


1.Spring Data Elasticsearch

可以访问spring官网查看其API的具体使用方式:https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#reference
在这里插入图片描述

Spring Data ElasticsearchElasticsearch 搜索引擎开发的解决方案。它提供了模板对象,用于存储、搜索、排序文档和构建聚合的高级API。

例如,Repository 使开发者能够通过定义具有自定义方法名称的接口来表达查询。

2.案例准备

Elasticsearch 中存储学生数据,并对学生数据进行搜索测试。

数据结构:

学号姓名性别出生日期
27张三2020-12-4

案例测试以下数据操作:

2.1 在 Elasticsearch 中创建 students 索引

在开始运行测试之前,在 Elasticsearch 中先创建 students 索引:

PUT /students
{"settings": {"number_of_shards": 3,"number_of_replicas": 2,"index.max_ngram_diff":30,"analysis": {"analyzer": {"ngram_analyzer": {"tokenizer": "ngram_tokenizer"}},"tokenizer": {"ngram_tokenizer": {"type": "ngram","min_gram": 1,"max_gram": 30,"token_chars": ["letter","digit"]}}}},"mappings": {"properties": {"id": {"type": "long"},"name": {"type": "text","analyzer": "ngram_analyzer"},"gender": {"type": "keyword"},"birthDate": {"type": "date","format": "yyyy-MM-dd"}}}
}

创建索引之后,kibana容器就不用使用了,因为其占用了比较多的内容,所以可以使用docker rm -f kibana删除kibana容器;
在这里插入图片描述

2.2 案例测试说明

通过对学生数据的CRUD操作,来使用Spring Data ElasticsearchAPI:

  1. C - 创建学生数据
  2. R - 访问学生数据
  3. U - 修改学生数据
  4. D - 删除学生数据
  5. 使用 Repository 和 Criteria 搜索学生数据

3.创建项目

3.1 新建工程

我们新建一个新的elasticsearchEmpty Project工程:
在这里插入图片描述

3.2 新建 springboot module,添加 spring data elasticsearch 依赖

在这里插入图片描述

3.3 pom.xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.6.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>cn.study</groupId><artifactId>spring-data-es</artifactId><version>1.0-SNAPSHOT</version><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

3.4 application.yml 配置

#logging.level.tracer=TRACE 作用是在控制台中显示底层的查询日志
spring:elasticsearch:rest:uris:- http://192.168.64.181:9200- http://192.168.64.181:9201- http://192.168.64.181:9202
# REST API调用的http协议数据日志
logging:level:tracer: TRACE

4.Student 实体类

package cn.study.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;/*** spring data es API 可以根据这里的设置,* 在服务器上自动创建索引,* 一般索引需要自己手动创建,不应依赖于客户端API自动创建* indexName:索引名,我们这里对应的是students* shards:可选属性,分片数量* replicas:可选属性,副本数量*/
@Document(indexName = "students",shards = 3,replicas = 2)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {// 使用学生的学号,作为索引id(_id字段)@Idprivate Long id;private String name;private Character gender;//@Field设置类中的属性对应索引中的字段名的关系,如果同名可以省略@Field("birthDate")          //索引中的字段名private String birthDate;    //对应类中的属性
}
  • @Document 注解
    • @Documnet注解对索引的参数进行设置。
    • 上面代码中,把 students 索引的分片数设置为3,副本数设置为2。
  • @Id 注解
    • 在 Elasticsearch 中创建文档时,使用 @Id 注解的字段作为文档的 _id 值
  • @Field 注解
    • 通过 @Field 注解设置字段的数据类型和其他属性。
  • 文本类型 text 和 keyword
    • text 类型会进行分词。
    • keyword 不会分词。
  • analyzer 指定分词器
    • 通过 analyzer 设置可以指定分词器,例如 ik_smart、ik_max_word 等。

我们这个例子中,对学生姓名字段使用的分词器是 ngram 分词器,其分词效果如下面例子所示:

字符串分词结果
刘德华
刘德
刘德华
德华

5.通过 ElasticsearchRepository 实现 CRUD 操作

Spring Data 的 Repository 接口提供了一种声明式的数据操作规范,无序编写任何代码,只需遵循 Spring Data 的方法定义规范即可完成数据的 CRUD 操作。

ElasticsearchRepository 继承自 Repository,其中已经预定义了基本的 CURD 方法,我们可以通过继承 ElasticsearchRepository,添加自定义的数据操作方法。

5.1 StudentRepository接口

package cn.study.es;import cn.study.entity.Student;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;/*** 我们这里基于Spring Data API 的Repository数据访问规范进行业务测试* 这种规范不需要我们自己完成相关代码,只需要定义抽象类,抽象方法就可以访问数据库的数据* * 接口中已经定义了基础的增删改查方法* 继承的接口中需要传入俩个参数(访问学生数据,ID是Long类型)*/
public interface StudentRepository extends ElasticsearchRepository<Student,Long> {}

5.2 业务类 StudentService

package cn.tedu.esspringboot.es;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class StudentService {@Autowiredprivate StudentRepository studentRepo;public void save(Student student) {studentRepo.save(student);}public void delete(Long id) {studentRepo.deleteById(id);}public void update(Student student) {save(student);}public List<Student> findByName(String name) {return studentRepo.findByName(name);}public List<Student> findByNameOrBirthDate(String name, String birthDate) {return studentRepo.findByNameOrBirthDate(name, birthDate);}
}

5.3 测试学生数据的 CRUD 操作

添加测试类,对学生数据进行 CRUD 测试

package cn.study;import cn.study.entity.Student;
import cn.study.es.StudentRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.Optional;@SpringBootTest
public class Test1 {@Autowiredprivate StudentRepository studentRepository;//调用API提供的save方法将数据存储到索引中@Testpublic void test1(){studentRepository.save(new Student(9527L,"卡布达",'男',"2023-10-11"));studentRepository.save(new Student(9528L,"蜻蜓队长",'男',"2023-10-12"));studentRepository.save(new Student(9529L,"鲨鱼辣椒",'男',"2023-10-13"));studentRepository.save(new Student(9530L,"蟑螂恶霸",'男',"2023-10-14"));studentRepository.save(new Student(9531L,"丸子滚滚",'男',"2023-10-15"));studentRepository.save(new Student(9532L,"蝎子莱莱",'男',"2023-10-16"));studentRepository.save(new Student(9533L,"金贵次郎",'男',"2023-10-17"));studentRepository.save(new Student(9534L,"呱呱蛙",'男',"2023-10-18"));studentRepository.save(new Student(9535L,"蜘蛛侦探",'男',"2023-10-19"));studentRepository.save(new Student(9536L,"呱呱蛙",'男',"2023-10-20"));studentRepository.save(new Student(9537L,"呱呱蛙",'男',"2023-10-21"));studentRepository.save(new Student(9538L,"呱呱蛙",'男',"2023-10-22"));studentRepository.save(new Student(9539L,"呱呱蛙",'男',"2023-10-23"));}//更新9527数据的名字和时间@Testpublic void test2(){studentRepository.save(new Student(9527L,"巨人卡布达",'男',"2023-10-19"));}/*** 查询操作:* java.util.Optinal 防止出现空指针异常*/@Testpublic void test3(){Optional<Student> op = studentRepository.findById(9527L);if(op.isPresent()){//判断内部包含的对象是否存在Student s = op.get();System.out.println(s);}System.out.println("----------------------------------------------");Iterable<Student> all = studentRepository.findAll();for (Student s :all) {System.out.println(s);}}//删除操作@Testpublic void test4(){studentRepository.deleteById(9530L);}
}

依次运行每个测试方法,并使用 head 观察测试结果

在这里插入图片描述

并且通过打印的日志我们可以看到,http请求通过PUT请求添加数据,通过POST请求获取状态标志:
在这里插入图片描述

6.使用 Repository 构建查询

Spring Data Elasticsearch 中,可以使用 SearchOperations 工具执行一些更复杂的查询,这些查询操作接收一个 Query 对象封装的查询操作。

Spring Data Elasticsearch 中的 Query 有三种:

  • CriteriaQuery
  • StringQuery
  • NativeSearchQuery

多数情况下,CriteriaQuery 都可以满足我们的查询求。下面来看两个 Criteria 查询示例:

6.1 Repository 方法命名规范

自定义数据操作方法需要遵循 Repository 规范,示例如下:

关键词方法名es查询
AndfindByNameAndPrice{ “query” : { “bool” : { “must” : [ { “query_string” : { “query” : “?”, “fields” : [ “name” ] } }, { “query_string” : { “query” : “?”, “fields” : [ “price” ] } } ] } }}
OrfindByNameOrPrice{ “query” : { “bool” : { “should” : [ { “query_string” : { “query” : “?”, “fields” : [ “name” ] } }, { “query_string” : { “query” : “?”, “fields” : [ “price” ] } } ] } }}
IsfindByName{ “query” : { “bool” : { “must” : [ { “query_string” : { “query” : “?”, “fields” : [ “name” ] } } ] } }}
NotfindByNameNot{ “query” : { “bool” : { “must_not” : [ { “query_string” : { “query” : “?”, “fields” : [ “name” ] } } ] } }}
BetweenfindByPriceBetween{ “query” : { “bool” : { “must” : [ {“range” : {“price” : {“from” : ?, “to” : ?, “include_lower” : true, “include_upper” : true } } } ] } }}
LessThanfindByPriceLessThan{ “query” : { “bool” : { “must” : [ {“range” : {“price” : {“from” : null, “to” : ?, “include_lower” : true, “include_upper” : false } } } ] } }}
LessThanEqualfindByPriceLessThanEqual{ “query” : { “bool” : { “must” : [ {“range” : {“price” : {“from” : null, “to” : ?, “include_lower” : true, “include_upper” : true } } } ] } }}
GreaterThanfindByPriceGreaterThan{ “query” : { “bool” : { “must” : [ {“range” : {“price” : {“from” : ?, “to” : null, “include_lower” : false, “include_upper” : true } } } ] } }}
GreaterThanEqualfindByPriceGreaterThan{ “query” : { “bool” : { “must” : [ {“range” : {“price” : {“from” : ?, “to” : null, “include_lower” : true, “include_upper” : true } } } ] } }}
BeforefindByPriceBefore{ “query” : { “bool” : { “must” : [ {“range” : {“price” : {“from” : null, “to” : ?, “include_lower” : true, “include_upper” : true } } } ] } }}
AfterfindByPriceAfter{ “query” : { “bool” : { “must” : [ {“range” : {“price” : {“from” : ?, “to” : null, “include_lower” : true, “include_upper” : true } } } ] } }}
LikefindByNameLike{ “query” : { “bool” : { “must” : [ { “query_string” : { “query” : “?*”, “fields” : [ “name” ] }, “analyze_wildcard”: true } ] } }}
StartingWithfindByNameStartingWith{ “query” : { “bool” : { “must” : [ { “query_string” : { “query” : “?*”, “fields” : [ “name” ] }, “analyze_wildcard”: true } ] } }}
EndingWithfindByNameEndingWith{ “query” : { “bool” : { “must” : [ { “query_string” : { “query” : “*?”, “fields” : [ “name” ] }, “analyze_wildcard”: true } ] } }}
Contains/ContainingfindByNameContaining{ “query” : { “bool” : { “must” : [ { “query_string” : { “query” : “?”, “fields” : [ “name” ] }, “analyze_wildcard”: true } ] } }}
In (when annotated as FieldType.Keyword)findByNameIn(Collectionnames){ “query” : { “bool” : { “must” : [ {“bool” : {“must” : [ {“terms” : {“name” : [“?”,“?”]}} ] } } ] } }}
InfindByNameIn(Collectionnames){ “query”: {“bool”: {“must”: [{“query_string”:{“query”: “”?" “?”", “fields”: [“name”]}}]}}}
NotIn (when annotated as FieldType.Keyword)findByNameNotIn(Collectionnames){ “query” : { “bool” : { “must” : [ {“bool” : {“must_not” : [ {“terms” : {“name” : [“?”,“?”]}} ] } } ] } }}
NotInfindByNameNotIn(Collectionnames){“query”: {“bool”: {“must”: [{“query_string”: {“query”: “NOT(”?" “?”)", “fields”: [“name”]}}]}}}
NearfindByStoreNear
TruefindByAvailableTrue{ “query” : { “bool” : { “must” : [ { “query_string” : { “query” : “true”, “fields” : [ “available” ] } } ] } }}
FalsefindByAvailableFalse{ “query” : { “bool” : { “must” : [ { “query_string” : { “query” : “false”, “fields” : [ “available” ] } } ] } }}
OrderByfindByAvailableTrueOrderByNameDesc{ “query” : { “bool” : { “must” : [ { “query_string” : { “query” : “true”, “fields” : [ “available” ] } } ] } }, “sort”:[{“name”:{“order”:“desc”}}] }

例如上表中的findByName方法,query后面的是当前方法的搜索关键词,fields字段后面跟着的就是查询的字段;

在这里插入图片描述

使用此类查询,一定遵循表格中的方法命名规范;

6.2 Repository API查询案例

我们在StudentRepository接口中构建Repository API提供的查询方法:

package cn.study.es;import cn.study.entity.Student;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;/*** 我们这里基于Spring Data API 的Repository数据访问规范进行业务测试* 这种规范不需要我们自己完成相关代码,只需要定义抽象类,抽象方法就可以访问数据库的数据** 接口中已经定义了基础的增删改查方法* 继承的接口中需要传入俩个参数(访问学生数据,ID是Long类型)*/
public interface StudentRepository extends ElasticsearchRepository<Student,Long> {//使用name字段搜索关键词List<Student> findByName(String key);//使用name字段或者birthdate字段中搜索关键词List<Student> findByNameOrBirthDate(String name ,String birthdate);}

一定要注意方法名验证遵循6.1 Repository 方法命名规范中的要求;

6.3 创建测试方法进行测试

package cn.study;import cn.study.entity.Student;
import cn.study.es.StudentRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;/*** Repository 构建查询案例* */
@SpringBootTest
public class Test2 {@Autowiredprivate StudentRepository studentRepository;@Testpublic void  test1(){//可以使用单独的关键字进行搜索List<Student> list1 = studentRepository.findByName("卡");for (Student  s1: list1) {System.out.println(s1);}System.out.println("------------------------");//但是对于日期是不分词的,无法通过分词进行搜索List<Student> list2 = studentRepository.findByNameOrBirthDate("呱", "2023-10-18");for (Student  s2: list2) {System.out.println(s2);}}}

7.分页操作

分页对于搜索来说十分重要,大量数据的操作必须进行分页操作,否则十分影响性能及客户体验;Repository API 同样提供了分页的工具;

7.1 Pageable

Pageable 封装了向服务器提交的分页参数–页数及每页数据 ,第1页数据,提交数据0,第2页数据,提交数据1,以此类推;

并且其提供了一个可选参数 page,封装服务器返回的这一页数据,以及所有的分页属性;

package cn.tedu.esspringboot.es;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.stereotype.Component;import java.util.List;
import java.util.stream.Collectors;@Component
public class StudentSearcher {@Autowiredprivate ElasticsearchOperations searchOperations;public List<Student> searchByBirthDate(String birthDate) {Criteria c = new Criteria("birthDate").is(birthDate);return criteriaSearch(c);}public List<Student> searchByBirthDate(String ge, String le) {Criteria c = new Criteria("birthDate").between(ge, le);return criteriaSearch(c);}private List<Student> criteriaSearch(Criteria c) {CriteriaQuery q = new CriteriaQuery(c);SearchHits<Student> hits = searchOperations.search(q, Student.class);List<Student> list = hits.stream().map(SearchHit::getContent).collect(Collectors.toList());return list;}
}

7.2 修改 StudentService

改造StudentService接口:

package cn.study.es;import cn.study.entity.Student;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;/*** 我们这里基于Spring Data API 的Repository数据访问规范进行业务测试* 这种规范不需要我们自己完成相关代码,只需要定义抽象类,抽象方法就可以访问数据库的数据** 接口中已经定义了基础的增删改查方法* 继承的接口中需要传入俩个参数(访问学生数据,ID是Long类型)*/
public interface StudentRepository extends ElasticsearchRepository<Student,Long> {//使用name字段搜索关键词List<Student> findByName(String key);//使用name字段或者birthdate字段中搜索关键词//List<Student> findByNameOrBirthDate(String name ,String birthdate);//改造findByNameOrBirthDate方法//List<Student> findByNameOrBirthDate(String name , String birthdate, Pageable pageable);//也可以改造为使用Page可选参数的方法Page<Student> findByNameOrBirthDate(String name , String birthdate, Pageable pageable);
}

7.3 在测试类中添加测试方法

package cn.study;import cn.study.entity.Student;
import cn.study.es.StudentRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;import java.util.List;/*** Repository 构建查询案例* */
@SpringBootTest
public class Test2 {@Autowiredprivate StudentRepository studentRepository;@Testpublic void  test1(){//可以使用单独的关键字进行搜索List<Student> list1 = studentRepository.findByName("卡");for (Student  s1: list1) {System.out.println(s1);}System.out.println("------------------------");//但是对于日期是不分词的,无法通过分词进行搜索
//        List<Student> list2 = studentRepository.findByNameOrBirthDate("呱", "2023-10-18");
//        for (Student  s2: list2) {
//            System.out.println(s2);
//        }//改造findByNameOrBirthDate方法//使用pageable的实现类PageRequest创建pageable对象,第1页,每页3条数据;Pageable pageable = PageRequest.of(0,3);Page<Student> list2 = studentRepository.findByNameOrBirthDate("呱", "2023-10-18", pageable );for (Student  s2: list2) {System.out.println(s2);}}}

8.查询结果的高亮显示

8.1 接口方法

我们在接口中创建新的方法findByNameNot来测试查询结果的高亮显示:

    //搜索不包含输入字段的关键词@Highlight(//设置parameters参数,通过@HighlightParameters设置前置preTags标签和postTags后置标签parameters = @HighlightParameters(preTags = "<em>",postTags = "</em>"),//设置fields高亮字段fields = {@HighlightField(name = "name")})List<SearchHit<Student>> findByNameNot(String key);

查询结果的高亮显示通过 @Highlight注解进行设置,其包含俩个参数:

  • parameters:需要通过@HighlightParameters注解作为值传入设置parameters高亮参数,@HighlightParameters注解还需要设置标签;
    • ·preTags·参数:设置前置标签;
    • postTags参数:设置后置标签
  • fields:通过@HighlightField注解作为值传入设置fields参数设置具体哪些字段高亮,@HighlightField注解还需要给定name参数的值
    • name参数:具体哪些字段高亮,@HighlightField注解中的参数为一个数组,通过数组的形式可以给定多个具体字段;

需要注意的是,此前我们创建的findByNameOrBirthDate不能使用高亮注解,使用高亮注解后,发送消息会同时将高亮注解中设置的相关参数也一起返回给客户端,Page类型与List类型均不可包含此些数据;

我们需要使用springboot封装的SearchHit类型将其与List,Student组成嵌套关系的返回类型,获取高亮结果;SearchHit中封装了高亮类型 的结果,我们Student对象中只包含原始学生数据,所以需要SearchHit来封装高亮字段的相关内容;
在这里插入图片描述

此时SearchHit里会包含高亮属性:name = xxx<em>卡</em>

8.2 测试类方法

    //查询结果高亮显示@Testpublic void test2(){List<SearchHit<Student>> list1 = studentRepository.findByNameNot("不包含此字段");List<Student> stuList = new ArrayList<>();for (SearchHit<Student>  sh: list1) {//取出学生对象Student stu = sh.getContent();//取出高亮对象中的name值List<String> name = sh.getHighlightField("name");//将高亮对象中的name值拼接好String hiName = pinjie(name);//将高亮name值放到学生对象中stu.setName(hiName);stuList.add(stu);}for (Student s : stuList) {System.out.println(s);}}private String pinjie(List<String> name){//name=["xxx","<em>卡</em>,"xxx","<em>卡</em>"]StringBuilder sbu = new StringBuilder();for (String sn : name) {sbu.append(sn);}return sbu.toString();}

9.使用 Criteria 构建查询

Spring Data Elasticsearch 中,除了ElasticsearchRepository外,还提供了CriteriaAPI ;可以使用 SearchOperations 工具执行一些更复杂的查询,这些查询操作接收一个 Query 对象封装的查询条件,然后使用CriteriaQuery封装Criteria对象分页参数等,最后使用ElasticsearchOperations执行Query 对象

区别于ElasticsearchRepository严格的方法命名规范,Criteria对方法命名没有任何要求;

Spring Data Elasticsearch 中的 Query 有三种:

  • CriteriaQuery
  • StringQuery
  • NativeSearchQuery

多数情况下,CriteriaQuery 都可以满足我们的查询求。下面来看两个 Criteria 查询示例:

9.1 StudentSearcher

package cn.study.es;import cn.study.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.List;@Component
public class StudentSearche {//用来执行查询的工具对象@Autowiredprivate ElasticsearchOperations elasticsearchOperations;//按照姓名搜索public List<Student> findByName(String name){//创建Criteria对象Criteria c = new Criteria("name");//在name字段搜索指定的关键词c.is(name);return exec(c,null);}//按照日期范围搜索,并添加分页public List<Student> findByBirthDate(String from, String to, Pageable pageable){//创建Criteria对象Criteria c = new Criteria("birthDate");//在name字段搜索指定的关键词c.between(from,to);return exec(c,pageable);}private List<Student> exec(Criteria c, Pageable pageable) {//使用CriteriaQuery封装Criteria对象CriteriaQuery q = new CriteriaQuery(c);if(pageable != null){q.setPageable(pageable);}//使用elasticsearchOperations对象进行搜索,并把搜索结果封装成student对象(默认返回是一个json串)SearchHits<Student> search = elasticsearchOperations.search(q, Student.class);List<Student> list = new ArrayList<>();for (SearchHit<Student> sh : search) {list.add(sh.getContent());}return list;}
}

9.2 在测试类中测试

package cn.study;import cn.study.entity.Student;
import cn.study.es.StudentSearche;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;import java.util.ArrayList;
import java.util.List;@SpringBootTest
public class Test3 {@Autowiredprivate StudentSearche studentSearche;@Testpublic void test1(){List<Student> list = studentSearche.findByName("呱");System.out.println(list);}@Testpublic void test2(){PageRequest p = PageRequest.of(0, 2);List<Student> list = studentSearche.findByBirthDate("2023-10-15","2023-10-19",p);System.out.println(list);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/114087.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在 Python 中使用 Pillow 进行图像处理【2/4】

第二部分 一、说明 该文是《在 Python 中使用 Pillow 进行图像处理》的第二部分&#xff0c;主要介绍pil库进行一般性处理&#xff1a;如&#xff1a;图像卷积、钝化、锐化、阈值分割。 二、在 Python 中使用 Pillow 进行图像处理 您已经学习了如何裁剪和旋转图像、调整图像大…

机器学习终极指南:统计和统计建模03/3 — 第 -3 部分

系列上文&#xff1a;机器学习终极指南&#xff1a;特征工程&#xff08;02/2&#xff09; — 第 -2 部分 一、说明 在终极机器学习指南的第三部分中&#xff0c;我们将了解统计建模的基础知识以及如何在 Python 中实现它们&#xff0c;Python 是一种广泛用于数据分析和科学计…

Spring Security认证架构介绍

在之前的Spring Security&#xff1a;总体架构中&#xff0c;我们讲到Spring Security整个架构是通过Bean容器和Servlet容器对过滤器的支持来实现的。我们将从过滤器出发介绍Spring Security的Servlet类型的认证架构。 1.AbstractAuthenticationProcessingFilter AbstractAut…

Git的介绍和命令汇总

目录 一、git介绍 1、git的工作区域 2、git中文件的四种状态 二、常用命令 1、基础命令 2、提交类命令 3、删除类命令 4、分支类相关命令 5、 查看类相关命令 6、撤销类命令 一、git介绍 1、git的工作区域 在Git中&#xff0c;有四个工作区域&#xff1a;工作区域&am…

CorelDRAW Graphics Suite2024完整版最新功能介绍

CorelDRAW平面设计软件通常也被叫做CDR&#xff0c;CDR广泛应用于排版印刷、矢量图形编辑及网页设计等领域。通过CorelDRAW体验极具个性的自由创作&#xff0c;大胆展现真我&#xff0c;交付出众的创意作品。CorelDRAW拥有矢量插图、页面布局、图片编辑和设计工具&#xff0c;无…

迅为RK3568开发板RTMP推流之视频监控

1 搭建 RTMP 媒流体服务器 nginx-rtmp 是一个基于 nginx 的 RTMP 服务模块&#xff0c;是一个功能强大的流媒体服务器模块&#xff0c; 它提供了丰富的功能和灵活的配置选项&#xff0c;适用于构建各种规模的流媒体平台和应用。无论是搭建实时视频直播平台、点播系统或多屏互…

leetcode 114. 二叉树展开为链表

2023.10.22 本题第一反应就是将 原二叉树的节点值 用先序遍历的方式保存到一个集合数组中。然后再重新构造出新的二叉树。 java代码如下&#xff1a; /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode rig…

我国跨境电商行业研究报告(2022)

我国跨境电商行业研究报告 我国跨境电商规模突飞猛进&#xff0c;2022年进出口规模超2万亿元&#xff0c;2023年上半年跨境电商出口8210亿元&#xff0c;增长19.9%。全国跨境电商主体已超10万家&#xff0c;近年来涌现出一批上市公司&#xff0c;以及广州希音等全球独角兽企业。…

curl命令服务器上执行http请求

1. 现在本地使用postman生成curl命令 注意: 将ip改成127.0.0.1,端口是实际服务运行的端口 curl --location --request POST http://127.0.0.1:63040/content/course/list?pageNo1&pageSize2 \ --header Content-Type: application/json \ --data-raw {"courseName&q…

GO学习之 goroutine的调度原理

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 9、GO学习之 接口(Interface) 10、GO学习之 网络通信(Net/Htt…

JavaSE入门---掌握面向对象三大特性:封装、继承和多态

文章目录 封装什么是封装&#xff1f;如何实现封装&#xff1f; 继承什么是继承&#xff1f;继承的语法父类成员访问子类访问父类的成员变量子类访问父类的成员方法 认识super关键字认识final关键字子类的构造方法super VS this在继承关系中各代码块的执行顺序是怎样的&#xf…

数据可视化与GraphQL:利用Apollo创建仪表盘

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…

YOLO目标检测——人脸识别数据集【对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;安全监控、智能驾驶、人机交互、人脸门禁、人脸支付、人脸搜索数据集说明&#xff1a;人脸识别数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富&#xff0c;含有人脸图片标签说明&#xff1a;使用lableimg标注软件标注&#xff0…

PHP 基础

PHP 基础 概述 在PHP 文件中&#xff0c;可以与HTML 和JavaScript 混编。 开始标记<?php 表示进入PHP 模式&#xff0c;结束标记?>&#xff0c;标识退出PHP 模式。 PHP 模式之外的内容会被作为字符输出到浏览器中。 PHP 在服务端执行&#xff0c;HTML 和 JS 在浏览…

【iOS】UITableView总结(Cell的复用原理、自定义Cell、UITableViewCell协议方法)

UITableView 列表的特点&#xff1a; 数据量大样式较为统一通常需要分组垂直滚动通常可视区只有一个 -> 视图的复用 UITableViewDataSource UITableView作为视图&#xff0c;只负责展示&#xff0c;协助管理&#xff0c;不管理数据 需要开发者为UITableView提供展示所需…

登上抖音热搜榜:如何让你的内容火爆全网

在当今信息爆炸的时代&#xff0c;抖音已经成为了很多人获取信息、娱乐和社交的重要平台。每一天&#xff0c;都有大量的短视频在抖音上诞生&#xff0c;然而&#xff0c;只有少数幸运儿能够登上抖音热搜榜&#xff0c;成为万人瞩目的焦点。那么&#xff0c;如何让你的内容火爆…

Go并发编程之四

一、前言 今天我们介绍一下Go并发编程另外一个重要概念【多路复用】&#xff0c;多路复用最开始是在网络通讯领域&#xff08;硬件&#xff09;应用&#xff0c;指的是用同一条线路承载多路信号进行通信的方式&#xff0c;有频分多路复用、时分多路复用等等技术&#xff0c;然…

MySQL日志 错误日志 二进制日志 查询日志 慢查询日志

一、错误日志 错误日志是MySQL中最重要的日志之一,它记录了当mysqld启动和停止时,以及服务器在运行过程中发生任何严重错误时的相关信息。当数据库出现任何故障导致无法正常使用时,建议首先查看此日志。 该日志是默认开启的&#xff0c;默认存放目录/var/log/,默认的日志文件名…

2019年亚太杯APMCM数学建模大赛A题基于图像分析的二氧化硅熔化表示模型求解全过程文档及程序

2019年亚太杯APMCM数学建模大赛 A题 基于图像分析的二氧化硅熔化表示模型 原题再现 铁尾矿的主要成分是二氧化硅&#xff0c;而二氧化硅是铁尾矿成分中最难熔化的部分。因此&#xff0c;铁尾矿的熔融行为可以用二氧化硅的熔融行为来表示。然而&#xff0c;高温熔池的温度超过…

Jmeter的性能测试

性能测试的概念 定义&#xff1a;软件的性能是软件的一种非功能特性&#xff0c;它关注的不是软件是否能够完成特定的功能&#xff0c;而是在完成该功能时展示出来的及时性。 由定义可知性能关注的是软件的非功能特性&#xff0c;所以一般来说性能测试介入的时机是在功能测试…