简介
Elasticsearch是一个开源的分布式搜索和分析引擎,它构建在Apache Lucene搜索引擎库之上。它提供了一个强大而灵活的全文搜索和分析解决方案,具有高性能、可扩展性和容错性。
以下是Elasticsearch的一些关键特点:
- 分布式架构:Elasticsearch被设计为一个分布式系统,可以在多个节点上存储和处理数据。它使用了分片和副本机制,实现了数据的分布式存储和冗余备份,提供了高可用性和容错性。
- 实时搜索:Elasticsearch能够在毫秒级别内提供实时搜索和分析能力。当数据被索引后,它几乎可以立即被搜索到,使得对实时数据的查询和分析变得高效。
- 全文搜索:Elasticsearch支持全文搜索,可以对文本数据进行全文索引和搜索。它使用了先进的倒排索引技术,可以快速地找到与搜索查询匹配的文档。
- 强大的查询语言:Elasticsearch提供了丰富而灵活的查询语言,使用JSON格式构建查询请求。您可以执行各种类型的查询,包括匹配、范围、布尔逻辑、聚合等,以满足不同的搜索和分析需求。
- 分布式聚合:Elasticsearch支持在分布式环境下执行聚合操作,可以对大规模数据集进行统计、分组、汇总等操作。这使得从海量数据中提取有意义的信息变得更加便捷和高效。
- 数据可扩展性:Elasticsearch具有良好的可扩展性,可以根据需要水平扩展节点和集群,以处理大规模数据和高并发请求。它支持动态增加或删除节点,以适应不断变化的工作负载。
- 插件生态系统:Elasticsearch拥有丰富的插件生态系统,可以扩展其功能。这些插件可以用于数据预处理、分析和可视化等领域,帮助用户更好地利用和探索数据。
Elasticsearch被广泛应用于各种场景,包括实时日志分析、搜索引擎、企业搜索、商业智能、安全分析等。它提供了简单易用的API和工具,使得开发人员可以轻松地集成和利用其强大的搜索和分析功能。
官网地址:www.elastic.co/cn/elastics…
基本概念
1.索引(index)
索引库,类似于数据库的概念
2.类型(type)
类似于mysql中的table概念,一个索引库下有很多不同索引(类似库下的不同表)。
3.文档(Document)
以JSON格式定义的特定方式的字段集合。每个文档都属于一种类型,并且位于索引内。每个文档都与一个称为UID的唯一标识符相关联。
4.字段(Field)
说明:字段就是文档中的属性。
5.映射配置
字段的数据类型、属性、是否索引、是否存储等特性。 基本概念
1.索引(index)
索引库,类似于数据库的概念
2.类型(type)
类似于mysql中的table概念,一个索引库下有很多不同索引(类似库下的不同表)。
3.文档(Document)
以JSON格式定义的特定方式的字段集合。每个文档都属于一种类型,并且位于索引内。每个文档都与一个称为UID的唯一标识符相关联。
4.字段(Field)
说明:字段就是文档中的属性。
5.映射配置
字段的数据类型、属性、是否索引、是否存储等特性。
数据类型
1.简单数据类型
- 字符串
- 数值
- 布尔
- 二进制:binary
- 范围类型
integer_range, float_range, long_range, double_range, date_range
- 日期:date
2.复杂类型
• 数组 [ ] Nested: nested (for arrays of JSON objects 数组类型的JSON对象)
• 对象 { } Object: object(for single JSON objects 单个JSON对象)
原生语法
当前有一个user对象,包括姓名,年龄,爱好,手机号码,邮箱,下面使用Kibana对它进行增删改查
1.写数据
#使用put请求需要带上文档ID
PUT /user_index/_doc/1
{ "name": "John Doe",
"age": 30,
"hobbies": ["Reading", "Hiking", "Photography"],
"phone": "1234567890",
"email": "johndoe@example.com"
}
#使用post请求不带文档ID,由es自动分配
POST /user_index/_doc
{ "name": "John Doe",
"age": 30,
"hobbies": ["Reading", "Hiking", "Photography"],
"phone": "1234567890",
"email": "johndoe@example.com" }
2.批量写数据
#批量插入使用Bulk API
POST /user_index/_bulk
{ "index": {} } { "name": "John shi", "age": 35, "hobbies": ["吃饭", "睡觉", "照相"], "phone": "1234567890", "email": "johndoe@example.com" }
{ "index": {} } { "name": "Jane Smith", "age": 28, "hobbies": ["游泳", "跑步"], "phone": "9876543210", "email": "janesmith@example.com" }
{ "index": {} } { "name": "Mike Johnson", "age": 35, "hobbies": ["旅游", "做饭"], "phone": "5555555555", "email": "mike@example.com" }
3.精确查询
#使用了"term"查询,同时指定了字段"name.keyword",这是一个未分词的关键字字段,它会精确匹配搜索词"John Doe"。
GET /user_index/_search
{ "query": {
"term": { "name.keyword": "John Doe"
}
}
}
4.模糊查询
GET /user_index/_search
{ "query": {
"match": {
"name": "John "
}
}
}
5.分页查询
#设置"from"参数为0,表示从第一条文档开始查询。通过设置"size"参数为10,表示每页查询10条文档 GET /user_index/_search
{ "query": {
"match_all": {}
},
"from": 1,
"size": 2
}
6.修改数据
POST /user_index/_update/1
{ "doc":
{ "name": "John Doe",
"age": 33,
"hobbies": ["Reading", "Hiking", "Photography", "Cooking"],
"phone": "9876543210",
"email": "johndoe_updated@example.com"
}
}
7.删除数据
#根据id删除
DELETE /user_index/_doc/1
springboot集成es
1.引用依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2.配置application.yml
spring:
elasticsearch:
rest:
uris: http://127.0.0.1:9200
3.代码实现
3.1 创建实体类
package com.demo.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* @description
* @author: irving-shi
* @date: 2023/8/4 10:28
*/
@Document(indexName = "es_user_index")
@Data
@AllArgsConstructor
public class EsUserInfo {
@Id
private Long id;
// 姓名
@Field(name = "name")
private String name;
// 年龄
private Integer age;
// 爱好
private List<String> hobby;
/**
* 入职时间
*/
@Field(name = "job_day",format= DateFormat.date_time)
private Date jobDay;
// 自我评价
private String selfEvaluation;
/**
* 薪资
*/
private BigDecimal salary;
}
@Document注解源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.data.elasticsearch.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.elasticsearch.index.VersionType;
import org.springframework.data.annotation.Persistent;
@Persistent
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Document {
String indexName(); //索引库的名称
/** @deprecated */
@Deprecated
String type() default ""; // 类型, 7.x之后已废弃
boolean useServerConfiguration() default false; //默认不使用es服务器的配置,使用代码中的配置
short shards() default 1; // 分片数
short replicas() default 1; // 每个分区默认的备份数
String refreshInterval() default "1s"; // 刷新间隔
String indexStoreType() default "fs"; //索引文件存储类型
boolean createIndex() default true; // 是否创建索引
VersionType versionType() default VersionType.EXTERNAL; //版本
}
@Field注解源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.data.elasticsearch.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@Documented
@Inherited
public @interface Field {
@AliasFor("name")
String value() default ""; //属性别名
@AliasFor("value")
String name() default ""; //属性别名
FieldType type() default FieldType.Auto; //属性类型,默认自动根据参数类型自动属性的类型
boolean index() default true; /默认情况下分词
DateFormat format() default DateFormat.none; //时间格式化
String pattern() default "";
boolean store() default false; //默认情况下不存储原文
boolean fielddata() default false;
String searchAnalyzer() default ""; //指定字段搜索时使用的分词器
String analyzer() default ""; ;//指定字段建立索引时指定的分词器
String normalizer() default "";//忽略某些字段
String[] ignoreFields() default {};
boolean includeInParent() default false;
String[] copyTo() default {};
int ignoreAbove() default -1;
boolean coerce() default true;
boolean docValues() default true;
boolean ignoreMalformed() default false;
IndexOptions indexOptions() default IndexOptions.none;
、、、、
}
3.2创建xxRepository
package com.demo.repository;
import com.demo.entity.EsUserInfo;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
/**
* @description
* @author: irving-shi
* @date: 2023/8/4 10:37
*/
//泛型的参数分别是实体类型和主键类型
public interface EsUserInfoRepository extends ElasticsearchRepository<EsUserInfo,Long> {
}
3.3 创建service
package com.demo.service;
import com.demo.entity.EsUserInfo;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import java.util.Iterator;
import java.util.List;
/**
* @description
* @author: irving-shi
* @date: 2023/8/4 10:39
*/
public interface EsUserInfoService {
void deleteIndex(Long id);
void save(EsUserInfo docBean);
void saveAll(List<EsUserInfo> list);
Iterator<EsUserInfo> findAll();
}
3。4 实现service
package com.demo.service.impl;
import com.demo.entity.EsUserInfo;
import com.demo.repository.EsUserInfoRepository;
import com.demo.service.EsUserInfoService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Iterator;
import java.util.List;
/**
* @description
* @author: irving-shi
* @date: 2023/8/4 0004 10:40
*/
@Service
public class EsUserInfoServiceImpl implements EsUserInfoService {
@Resource
private EsUserInfoRepository esUserInfoRepository;
@Override
public void deleteIndex(Long id) {
esUserInfoRepository.deleteById(id);
}
@Override
public void save(EsUserInfo docBean) {
esUserInfoRepository.save(docBean);
}
@Override
public void saveAll(List<EsUserInfo> list) {
esUserInfoRepository.saveAll(list);
}
@Override
public Iterator<EsUserInfo> findAll() {
return esUserInfoRepository.findAll().iterator();
}
}
除了上述自带默认默认方法,还有类型jpa的实现,根据方法名,自动去实现
package com.demo.repository;
import com.demo.entity.EsUserInfo;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
/**
* @description
* @author: irving-shi
* @date: 2023/8/4 10:37
*/
//泛型的参数分别是实体类型和主键类型
public interface EsUserInfoRepository extends ElasticsearchRepository<EsUserInfo,Long> {
// 满足姓名和年龄条件
List<EsUserInfo> findByNameAndAge(String name, Integer age);
// 满足姓名或者年龄条件
List<EsUserInfo> findByNameOrAge(String name,Integer age);
// 不包含某某姓名条件
Page<EsUserInfo> findByNameNot(String name, Pageable page);
// 分页查询
Page<EsUserInfo> findByName(String name, Pageable page);
// LIKE 语句查询
Page<EsUserInfo> findByNameLike(String name, Pageable page);
}
Elasticsearch 支持的关键字列表如下所示
Keyword | Sample | Elasticsearch Query String |
---|---|---|
And | findByNameAndPrice | { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } }, { "query_string" : { "query" : "?", "fields" : [ "price" ] } } ] } }} |
Or | findByNameOrPrice | { "query" : { "bool" : { "should" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } }, { "query_string" : { "query" : "?", "fields" : [ "price" ] } } ] } }} |
Is | findByName | { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } } ] } }} |
Not | findByNameNot | { "query" : { "bool" : { "must_not" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } } ] } }} |
Between | findByPriceBetween | { "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }} |
LessThan | findByPriceLessThan | { "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : false } } } ] } }} |
LessThanEqual | findByPriceLessThanEqual | { "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }} |
GreaterThan | findByPriceGreaterThan | { "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : false, "include_upper" : true } } } ] } }} |
GreaterThanEqual | findByPriceGreaterThan | { "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : true, "include_upper" : true } } } ] } }} |
Before | findByPriceBefore | { "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }} |
After | findByPriceAfter | { "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : true, "include_upper" : true } } } ] } }} |
Like | findByNameLike | { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }} |
StartingWith | findByNameStartingWith | { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }} |
EndingWith | findByNameEndingWith | { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "*?", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }} |
Contains/Containing | findByNameContaining | { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "*?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }} |
In (when annotated as FieldType.Keyword) | findByNameIn(Collection<String>names) | { "query" : { "bool" : { "must" : [ {"bool" : {"must" : [ {"terms" : {"name" : ["?","?"]}} ] } } ] } }} |
In | findByNameIn(Collection<String>names) | { "query": {"bool": {"must": [{"query_string":{"query": ""?" "?"", "fields": ["name"]}}]}}} |
NotIn (when annotated as FieldType.Keyword) | findByNameNotIn(Collection<String>names) | { "query" : { "bool" : { "must" : [ {"bool" : {"must_not" : [ {"terms" : {"name" : ["?","?"]}} ] } } ] } }} |
NotIn | findByNameNotIn(Collection<String>names) | {"query": {"bool": {"must": [{"query_string": {"query": "NOT("?" "?")", "fields": ["name"]}}]}}} |
Near | findByStoreNear | Not Supported Yet ! |
True | findByAvailableTrue | { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "true", "fields" : [ "available" ] } } ] } }} |
False | findByAvailableFalse | { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "false", "fields" : [ "available" ] } } ] } }} |
OrderBy | findByAvailableTrueOrderByNameDesc | { "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "true", "fields" : [ "available" ] } } ] } }, "sort":[{"name":{"order":"desc"}}] } |
单元测试
package com.demo.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.demo.ApplicationRunning;
import com.demo.entity.EsUserInfo;
import com.demo.repository.EsUserInfoRepository;
import com.demo.service.EsUserInfoService;
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 org.springframework.data.domain.Pageable;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @description
* @author: irving-shi
* @date: 2023/8/4 10:48
*/
@SpringBootTest(classes = ApplicationRunning.class)
public class EsUserInfoServiceImplTest {
@Autowired
private EsUserInfoService esUserInfoService;
@Resource
private EsUserInfoRepository esUserInfoRepository;
@Test
public void deleteIndex() {
esUserInfoRepository.deleteAll();
}
@Test
public void save() throws Exception{
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
esUserInfoService.save( new EsUserInfo(1000L, "张五", 20, Arrays.asList("骑马","编程","游泳"), simpleDateFormat.parse("2019-09-10"), "精通java编程,擅长游泳",new BigDecimal(3000)));
}
@Test
public void saveAll() throws Exception{
List<EsUserInfo> list = new ArrayList<>();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
list.add(new EsUserInfo(1001L, "张三", 20, Arrays.asList("骑马","编程","游泳"), simpleDateFormat.parse("2019-09-10"), "精通java编程,擅长游泳",new BigDecimal(3000)));
list.add(new EsUserInfo(1002L, "张思", 19, Arrays.asList("吃饭","喝酒","游泳"), simpleDateFormat.parse("2019-09-10"), "精通前端编码",new BigDecimal(3400)));
list.add(new EsUserInfo(1003L, "张武", 20, Arrays.asList("睡觉","看书"), simpleDateFormat.parse("2019-09-10"), "精通mysql、redis等,并且热爱生活",new BigDecimal(3200)));
list.add(new EsUserInfo(1004L, "李一", 21, Arrays.asList("骑马","编程","游泳"), simpleDateFormat.parse("2019-09-10"), "天下第一人",new BigDecimal(4563)));
list.add(new EsUserInfo(1005L, "李三", 23, Arrays.asList("做饭","编程","睡觉"), simpleDateFormat.parse("2019-09-10"), "明日说唱明星",new BigDecimal(3456)));
list.add(new EsUserInfo(1006L, "王二", 24, Arrays.asList("篮球","编程","游泳"), simpleDateFormat.parse("2019-09-10"), "篮球打的好,像那个男人",new BigDecimal(5432)));
list.add(new EsUserInfo(1007L, "三六小", 24, Arrays.asList("篮球","睡觉","游泳"), simpleDateFormat.parse("2019-09-10"), "无",new BigDecimal(3800)));
list.add(new EsUserInfo(1008L, "吴小", 24, Arrays.asList("篮球","甜品"), simpleDateFormat.parse("2019-09-10"), "喜欢睡觉,篮球,唱跳,rap",new BigDecimal(2999)));
list.add(new EsUserInfo(1009L, "吴天里", 24, Arrays.asList("羽毛球","睡觉"), simpleDateFormat.parse("2019-09-10"), "无",new BigDecimal(3200)));
list.add(new EsUserInfo(1010L, "吴测试", 19, Arrays.asList("足球","跑步","游泳"), simpleDateFormat.parse("2019-09-10"), "无",new BigDecimal(3555)));
esUserInfoService.saveAll(list);
}
@Test
public void findAll() {
System.out.println(JSON.toJSONString(esUserInfoService.findAll(), SerializerFeature.PrettyFormat));
}
@Test
public void findByNameAndAge() {
System.out.println(JSON.toJSONString(esUserInfoService.findByNameAndAge("张三",20), SerializerFeature.PrettyFormat));
System.out.println(JSON.toJSONString(esUserInfoService.findByNameAndAge("张三",19), SerializerFeature.PrettyFormat));
}
@Test
public void findByNameOrAge() {
System.out.println(JSON.toJSONString(esUserInfoService.findByNameOrAge("张三",20), SerializerFeature.PrettyFormat));
System.out.println(JSON.toJSONString(esUserInfoService.findByNameOrAge("张三",19), SerializerFeature.PrettyFormat));
}
@Test
public void findByNameNot() {
int pageNo = 0;
int pageSize = 5;
Pageable pageable = PageRequest.of(pageNo, pageSize);
System.out.println(JSON.toJSONString(esUserInfoService.findByNameNot("张三",pageable), SerializerFeature.PrettyFormat));
}
@Test
public void findByName() {
int pageNo = 0;
int pageSize = 5;
Pageable pageable = PageRequest.of(pageNo, pageSize);
System.out.println(JSON.toJSONString(esUserInfoService.findByName("张",pageable), SerializerFeature.PrettyFormat));
}
@Test
public void findByNameLike() {
int pageNo = 0;
int pageSize = 5;
Pageable pageable = PageRequest.of(pageNo, pageSize);
System.out.println(JSON.toJSONString(esUserInfoService.findByNameLike("小",pageable), SerializerFeature.PrettyFormat));
}
}
除上面方法之外,我们还可以用NativeSearchQueryBuilder进行高亮查询
package com.demo.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.demo.ApplicationRunning;
import com.demo.entity.EmployeeInfo;
import com.demo.entity.EsUserInfo;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHitSupport;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.SearchPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* @description
* @author: irving-shi
* @date: 2023/8/4 9:33
*/
@SpringBootTest(classes = ApplicationRunning.class)
public class EsUserHighLevelSearchTest {
@Resource
private ElasticsearchRestTemplate elasticsearchRestTemplate;
/**
* 精确查询
* 注:查询年龄20的记录
*/
@Test
public void findByNameTest() {
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
nativeSearchQueryBuilder.withQuery(QueryBuilders.termQuery("name.keyword", "张三"));
println(nativeSearchQueryBuilder);
}
/**
* AND 语句查询
* 注:查询姓名为张三,年龄为19的记录
*/
@Test
public void findByNameAndAgeTest() {
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
// 场景bool查询
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("name", "张三")).must(
QueryBuilders.matchQuery("age", 20)
);
nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
println(nativeSearchQueryBuilder);
}
/**
* OR 语句查询
*
* 注:查询姓名为张三,或者年龄为18的记录
*/
@Test
public void findByNameOrAgeTest() {
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
// 场景bool查询
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.should(QueryBuilders.matchPhraseQuery("name","张三")).should(QueryBuilders.matchQuery("age", 20));
nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
println(nativeSearchQueryBuilder);
}
/**
* 聚合查询-groupBy
*/
@Test
public void groupByAge() {
//1.构建查询对象
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("groupByAge").field("age").size(30));
SearchHits<EmployeeInfo> search = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), EmployeeInfo.class);
Aggregations aggregations = search.getAggregations();
ParsedLongTerms parsedLongTerms = aggregations.get("groupByAge");
List<String> ageList = parsedLongTerms.getBuckets().stream().map(Terms.Bucket::getKeyAsString).collect(Collectors.toList());
System.out.println(ageList);
}
/**
* 分页查询
* 带参数
*/
@Test
public void listPageMatch() {
int pageNo = 1;
int pageSize = 5;
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
nativeSearchQueryBuilder.withQuery(QueryBuilders.matchQuery("name","小"));
//注:Pageable类中 pageNum需要减1,如果是第一页 数值为0
Pageable pageable = PageRequest.of(pageNo-1,pageSize);
SearchHits<EmployeeInfo> searchHitsResult = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), EmployeeInfo.class);
//7.获取分页数据
SearchPage<EmployeeInfo> searchPageResult = SearchHitSupport.searchPageFor(searchHitsResult,pageable);
System.out.println("分页查询");
System.out.println(String.format("totalPages:%d, pageNo:%d, size:%d", searchPageResult.getTotalPages(), pageNo, pageSize));
System.out.println(JSON.toJSONString(searchPageResult.getSearchHits(), SerializerFeature.PrettyFormat));
}
/**
* 打印高亮查询对象,对象列表打印
*/
private void println(NativeSearchQueryBuilder nativeSearchQueryBuilder) {
SearchHits<EsUserInfo> search = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), EsUserInfo.class);
List<EsUserInfo> employeeInfoList = new ArrayList<>();
search.forEach(
s -> {
EsUserInfo esUserInfo = s.getContent();
employeeInfoList.add(esUserInfo);
}
);
System.out.println(JSON.toJSONString(search.getSearchHits(), SerializerFeature.PrettyFormat));
System.out.println(employeeInfoList);
}
}
另外对于复杂的聚合查询后续将进行补充学习