gitee:springboot整合elasticsearch
<modules>
<module>springboot-resthighlevelclientmodule>
<module>springboot-elasticsearchresttemplatemodule>
modules>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.5version>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<version>2.4.5version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-elasticsearchartifactId>
<version>2.4.5version>
dependency>
<dependency>
<groupId>org.elasticsearch.clientgroupId>
<artifactId>elasticsearch-rest-high-level-clientartifactId>
<version>7.6.2version>
dependency>
<dependency>
<groupId>org.elasticsearch.clientgroupId>
<artifactId>elasticsearch-rest-clientartifactId>
<version>7.6.2version>
dependency>
<dependency>
<groupId>org.elasticsearchgroupId>
<artifactId>elasticsearchartifactId>
<version>7.6.2version>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.1.0version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.16version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.13.2version>
<scope>testscope>
dependency>
dependencies>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<version>2.4.5version>
dependency>
<dependency>
<groupId>org.elasticsearch.clientgroupId>
<artifactId>elasticsearch-rest-high-level-clientartifactId>
dependency>
<dependency>
<groupId>org.elasticsearch.clientgroupId>
<artifactId>elasticsearch-rest-clientartifactId>
dependency>
<dependency>
<groupId>org.elasticsearchgroupId>
<artifactId>elasticsearchartifactId>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.13.2version>
<scope>testscope>
dependency>
dependencies>
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.153.133:3306/es?useUnicode=true&characterEncoding=utf-8
username: root
password: root
elasticsearch:
rest:
uris: http://192.168.153.133:9200
mybatis-plus:
type-aliases-package: com.qq.es.pojo
package com.qq.es.document;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
/**
* @author 黔程似景
* @description 商品文档对象
* @date 2023/6/17 12:07
* @blame 黔程似景
**/
@Data
@Document(indexName = "goods")
public class GoodsDocument {
@Id
private Long id;//把id字段作为文档主键
//商品标题
@Field(type = FieldType.Text , analyzer = "ik_smart")//指定问字段类型,分词器类型
private String title;//title使用ik分词器分词
//商品价格
@Field(type = FieldType.Double)
private Double price;
//商品库存
@Field(type = FieldType.Integer)
private Integer num;
//商品类别
@Field(type = FieldType.Keyword)//此处为不用分词
private String category;
//品牌名称
@Field(type = FieldType.Keyword)
private String brand;
}
package com.qq.es.repository;
import com.qq.es.document.GoodsDocument;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
/**
* @author 黔程似景
* @description es操作
* @date 2023/6/17 12:07
* @blame 黔程似景
**/
public interface GoodsRepository extends ElasticsearchRepository<GoodsDocument,Long> {
}
package com.qq.es.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* @author 黔程似景
* @description sql商品表
* @date 2023/6/17 12:07
* @blame 黔程似景
**/
@Data
@TableName("goods")
public class Goods {
//商品id
@TableId(type = IdType.AUTO)
private Long id;
//商品标题
private String title;
//商品价格
private Double price;
//商品库存
private Integer num;
//商品类别
private String category;
//品牌名称
private String brand;
}
package com.qq.es.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qq.es.pojo.Goods;
/**
* @author 黔程似景
* @description 查询商品mapper
* @date 2023/6/17 12:07
* @blame 黔程似景
**/
public interface GoodsMapper extends BaseMapper<Goods> {
}
package com.qq.es.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author 黔程似景
* @description 类型转换工具
* @date 2023/6/17 12:07
* @blame 黔程似景
**/
@Slf4j
public class BeanHelper {
public static <T> T copyProperties(Object source, Class<T> target){
try {
T t = target.newInstance();
BeanUtils.copyProperties(source, t);
return t;
} catch (Exception e) {
log.error("【数据转换】数据转换出错,目标对象{}构造函数异常", target.getName(), e);
return null;
}
}
public static <T> List<T> copyWithCollection(List<?> sourceList, Class<T> target){
try {
return sourceList.stream().map(s -> copyProperties(s, target)).collect(Collectors.toList());
} catch (Exception e) {
log.error("【数据转换】数据转换出错,目标对象{}构造函数异常", target.getName(), e);
return null;
}
}
public static <T> Set<T> copyWithCollection(Set<?> sourceList, Class<T> target){
try {
return sourceList.stream().map(s -> copyProperties(s, target)).collect(Collectors.toSet());
} catch (Exception e) {
log.error("【数据转换】数据转换出错,目标对象{}构造函数异常", target.getName(), e);
return null;
}
}
}
package com.qq.es;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author 黔程似景
* @description 启动类
* @date 2023/6/17 11:45
* @blame 黔程似景
**/
@SpringBootApplication
public class ApplicationStarter {
public static void main(String[] args) {
SpringApplication.run(ApplicationStarter.class , args);
}
}
package com.qq.es.test.mapper;
import com.qq.es.document.GoodsDocument;
import com.qq.es.mapper.GoodsMapper;
import com.qq.es.pojo.Goods;
import com.qq.es.repository.GoodsRepository;
import com.qq.es.utils.BeanHelper;
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.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class GoodsTest {
@Autowired
private GoodsMapper goodsMapper;
@Autowired
private GoodsRepository goodsRepository;
/**
* 批量导入
*/
@Test
public void testImportData(){
//从mysql中读取数据
List<Goods> goods = goodsMapper.selectList(null);
System.out.println(goods.size());
//2. 从goods对象转换成gooddocument对象集合
List<GoodsDocument> goodsDocuments = BeanHelper.copyWithCollection(goods, GoodsDocument.class);
//批量导入goodDocument对象
goodsRepository.saveAll(goodsDocuments);
}
}
package com.qq.es.test.mapper;
import com.qq.es.document.GoodsDocument;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.metrics.Avg;
import org.elasticsearch.search.aggregations.metrics.Max;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.Test;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.ArrayList;
import java.util.List;
@SpringBootTest
@RunWith(SpringRunner.class)
public class SelectGoodsEsTest {
@Autowired
private ElasticsearchRestTemplate restTemplate;
/*
es查询所有数据
get goods/_search
{
"query":{
"match_all":{}
}
}
*/
@Test
public void testMatchAll() {
//1. 创建查询构造器对象
NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
//2. 在查询构造器中添加各种条件
searchQueryBuilder.withQuery(QueryBuilders.matchAllQuery());
//3. 创建查询对象
NativeSearchQuery searchQuery = searchQueryBuilder.build();
//4. 进行查询 searchHits:封装所有查询结果
SearchHits<GoodsDocument> searchHits = restTemplate.search(searchQuery, GoodsDocument.class);
//处理结果
List<GoodsDocument> list = new ArrayList<>();
for (SearchHit<GoodsDocument> searchHit : searchHits) {
GoodsDocument goodsDocument = searchHit.getContent();
list.add(goodsDocument);
}
System.out.println("集合长度:" + list.size());
System.out.println(list);
}
/*
不分词查询查询term---------------->输入的是什么,就会搜什么,不进行分词
# 精准查询包含某个词的文档
GET goods/_search
{
"query": {
"term": {
"title": {
"value": "老人"
}
}
}
}
*/
@Test
public void testTermQuery() {
//1. 创建查询构造器对象
NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
//2. 注入条件
searchQueryBuilder.withQuery(QueryBuilders.termQuery("title", "老人"));
//3. 创建查询对象
NativeSearchQuery searchQuery = searchQueryBuilder.build();
//4. 查询获取结果
SearchHits<GoodsDocument> searchHits = restTemplate.search(searchQuery, GoodsDocument.class);
//5. 处理结果
List<GoodsDocument> list = new ArrayList<>();
for (SearchHit<GoodsDocument> searchHit : searchHits) {
GoodsDocument goodsDocument = searchHit.getContent();
System.out.println(goodsDocument);
list.add(goodsDocument);
}
System.out.println("拿到:" + list.size() + "条数据");
}
/*
# 对查询条件进行分词后查询,取并集
GET goods/_search
{
"query": {
"match": {
"title": "我要一部老人手机"
}
}
}
*/
@Test
public void testMatchQuery() {
//1. 创建查询构造器对象:用于查询对象
NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
//2. 注入查询条件
searchQueryBuilder.withQuery(QueryBuilders.matchQuery("title", "我要一部老人手机"));
//3. 创建查询条件对象
NativeSearchQuery searchQuery = searchQueryBuilder.build();
//查询
SearchHits<GoodsDocument> searchHits = restTemplate.search(searchQuery, GoodsDocument.class);
//获取数量
System.out.println(searchHits.getTotalHits());
//5. 处理结果
List<GoodsDocument> list = new ArrayList<>();
for (SearchHit<GoodsDocument> searchHit : searchHits) {
GoodsDocument goodsDocument = searchHit.getContent();
list.add(goodsDocument);
}
System.out.println("分词查询到" + list.size() + "条数据");
}
/*
# 对查询条件进行分词后查询,取交集
GET goods/_search
{
"query": {
"match": {
"title": {
"query": "老人手机",
"operator": "and"
}
}
}
}
*/
@Test
public void testMatchAndQuery() {
//1. 创建查询条件构造器对象:用于查询对象
NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
//2. 注入查询条件
searchQueryBuilder.withQuery(QueryBuilders.matchQuery("title", "老人手机").operator(Operator.AND));
//3. 创建查询条件对象
NativeSearchQuery searchQuery = searchQueryBuilder.build();
//4. 根据查询条件,查询结果
SearchHits<GoodsDocument> searchHits = restTemplate.search(searchQuery, GoodsDocument.class);
//5. 查询数据条数
System.out.println("分词查询交集一共有:" + searchHits.getTotalHits() + "条数据");
}
/*
# 对数字进行范围查询(price在2000~3000的数据)
GET goods/_search
{
"query": {
"range": {
"price": {
"gte": 2000,
"lte": 2500
}
}
}
}
*/
@Test
public void testRangeQuery() {
//1. 创建查询条件构造器对象:用于查询对象
NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
//2. 注入查询条件
searchQueryBuilder.withQuery(QueryBuilders.rangeQuery("price").gte(2000).lte(2500));
//3. 生成查询对象
NativeSearchQuery searchQuery = searchQueryBuilder.build();
//4. 根据查询条件对象,查询结果
SearchHits<GoodsDocument> searchHits = restTemplate.search(searchQuery, GoodsDocument.class);
//5. 查询数据条数
System.out.println("price在2000~2500的数据一共有:" + searchHits.getTotalHits() + "条数据");
}
/*
# 模糊查询
GET goods/_search
{
"query": {
"wildcard": {
"title": {
"value": "华*"
}
}
}
}
*/
@Test
public void testWildcardQuery() {
//1. 创建查询条件构造器对象:用于查询对象
NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
//2. 注入查询条件
searchQueryBuilder.withQuery(QueryBuilders.wildcardQuery("title", "华*"));
//3. 生成查询条件对象
NativeSearchQuery searchQuery = searchQueryBuilder.build();
//4. 根据查询对象查询结果
SearchHits<GoodsDocument> searchHits = restTemplate.search(searchQuery, GoodsDocument.class);
//5. 查询数据条数
System.out.println("模糊查询(其中词条以华开头的)有:" + searchHits.getTotalHits() + "条数据");
}
/*
* 分页查询+倒序查询
# 分页降序查询(50条每页,以price降序)
GET goods/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size": 50,
"sort": [
{
"price": {
"order": "desc"
}
}
]
}
*/
@Test
public void testPageAndSort() {
//1. 创建查询条件构造器对象:用于查询对象
NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
//2. 注入查询条件
//查询所有
searchQueryBuilder.withQuery(QueryBuilders.matchAllQuery());
//分页
int page = 1;
int pageSize = 10;
searchQueryBuilder.withPageable(PageRequest.of(page - 1, pageSize));
searchQueryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));
//3. 生成查询条件对象
NativeSearchQuery searchQuery = searchQueryBuilder.build();
//4. 根据查询对象查询结果
SearchHits<GoodsDocument> searchHits = restTemplate.search(searchQuery, GoodsDocument.class);
//5. 查询数据条数
System.out.println("模糊查询(其中词条以华开头的)有:" + searchHits.getTotalHits() + "条数据");
List<GoodsDocument> list = new ArrayList<>();
for (SearchHit<GoodsDocument> searchHit : searchHits) {
GoodsDocument goodsDocument = searchHit.getContent();
list.add(goodsDocument);
}
System.out.println("当前页有" + list.size() + "条数据");
}
/*
# 高亮查询
GET goods/_search
{
"query": {
"match": {
"title": "华为手机"
}
},
"highlight": {
"fields": {
"title": {
"pre_tags": "",
"post_tags": ""
}
}
}
}
*/
@Test
public void testHighLight() {
//1. 创建查询条件构造器对象:用于查询对象
NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
//2. 注入查询条件
//查询所有
searchQueryBuilder.withQuery(QueryBuilders.matchQuery("title", "华为手机"));
//高亮设置
HighlightBuilder.Field field = new HighlightBuilder.Field("title");
field.preTags("");
field.postTags("");
//注入高亮条件
searchQueryBuilder.withHighlightFields(field);
//3. 生成查询条件对象
NativeSearchQuery searchQuery = searchQueryBuilder.build();
//4. 查询
SearchHits<GoodsDocument> searchHits = restTemplate.search(searchQuery, GoodsDocument.class);
List<GoodsDocument> list = new ArrayList<>();
for (SearchHit<GoodsDocument> searchHit : searchHits) {
GoodsDocument goodsDocument = searchHit.getContent();
//取出高亮
List<String> titleList = searchHit.getHighlightFields().get("title");
//判断titleList是否为空,不为空则替换原有的title
if (titleList != null) {
goodsDocument.setTitle(titleList.get(0));
}
list.add(goodsDocument);
}
list.forEach(System.out::println);
}
/*
# 聚合查询
GET goods/_search
{
"aggs": {
"priceAvg": {
"avg": {
"field": "price"
}
}
}
}
*/
@Test
public void testAggreationQuery() {
//1. 创建查询条件构造器对象
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
//2. 注入条件-->查询平均价格
queryBuilder.addAggregation(AggregationBuilders.avg("priceAvg").field("price"));
//3. 生成查询条件对象
NativeSearchQuery searchQuery = queryBuilder.build();
//4. 查询
SearchHits<GoodsDocument> searchHits = restTemplate.search(searchQuery, GoodsDocument.class);
Aggregations aggregations = searchHits.getAggregations();
Avg avg = aggregations.get("priceAvg");
System.out.println("聚合查询求平均分:" + avg.getValue());
}
/*
* 查询最贵的华为
GET goods/_search
{
"query": {
"match": {
"title": "华为"
}
}
, "aggs": {
"max_price": {
"max": {
"field": "price"
}
}
}
}
*/
@Test
public void testPriceMax(){
//1. 创建查询构造器对象
NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
//2. 注入查询条件---->查询条件
searchQueryBuilder.withQuery(QueryBuilders.matchQuery("title" , "华为")).addAggregation(AggregationBuilders.max("max_price").field("price"));
//3. 生成查询对象
NativeSearchQuery searchQuery = searchQueryBuilder.build();
//4. 查询
SearchHits<GoodsDocument> searchHits = restTemplate.search(searchQuery, GoodsDocument.class);
//5. 取出结果
List<GoodsDocument> list = new ArrayList<>();
for (SearchHit<GoodsDocument> searchHit : searchHits) {
GoodsDocument goodsDocument = searchHit.getContent();
list.add(goodsDocument);
}
Aggregations aggregations = searchHits.getAggregations();
Max max = aggregations.get("max_price");
System.out.println(max.getValue());
list.forEach(System.out::println);
}
}
spring:
elasticsearch:
rest:
uris: 192.168.153.133:9200
package com.qq.es.service.impl;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
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.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author 黔程似景
* @description 使用RestHighLevelClient进行es相关的增删改查
* @date 2023/6/17 12:07
* @blame 黔程似景
**/
@Service
public class RestHighLevelService {
@Autowired
private RestHighLevelClient client;
/**
* 创建索引
* @param index 索引名称
*/
public boolean createIndex(String index , String source) {
boolean result = false;
//1.创建添加索引库请求,指定索引库名称
CreateIndexRequest indexRequest = new CreateIndexRequest(index);
indexRequest.mapping(source , XContentType.JSON);
try {
//2.执行操作,获取返回值
CreateIndexResponse createIndexResponse = client.indices().create(indexRequest, RequestOptions.DEFAULT);
//3.创建结果
result = createIndexResponse.isAcknowledged();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
/**
* 添加文档
*
* @param index 索引名
* @param data 文档内容
* @return
*/
public String addOrUpdateDoc(String index, String id, Map<String, Object> data) {
//1.创建添加文档的请求,设置索引库名称,数据,是否有id
IndexRequest request = new IndexRequest(index);
if (id != null){
request.id(id);
}
request.source(data);
//2.执行请求,获取响应
try {
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
return response.getId();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 删除文档
*
* @param index 索引名
* @param id id
* @return 文档id
*/
public String deleteDoc(String index, String id) {
//1.创建请求对象
DeleteRequest request = new DeleteRequest("itheima").id("1");
//2.执行请求,获取响应
try {
DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
return response.getId();
} catch (IOException e) {
e.printStackTrace();
}
//3.输出结果
return null;
}
/**
* 删除索引
*
* @param index 索引名称
*/
public boolean deleteIndex(String index) {
boolean result = false;
DeleteIndexRequest indexRequest = new DeleteIndexRequest(index);
try {
AcknowledgedResponse delete = client.indices().delete(indexRequest, RequestOptions.DEFAULT);
result = delete.isAcknowledged();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
/**
* 指定索引进行全查询
*/
public List<Map<String, Object>> matchAllQuery(String index , int page , int size) {
List<Map<String, Object>> list = new ArrayList<>();
SearchRequest request = new SearchRequest(index);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery()).from((page-1)*size).size(size);
request.source(builder);
try {
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
Map<String, Object> source = hit.getSourceAsMap();
list.add(source);
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
/**
* 对指定的字段进行条件查询,其中对查询条件进行分词之后查询【取并集】
* @param index 索引
* @param page 当前页码
* @param size 页大小
* @param field 查询字段
* @param value 查询条件
* @param operator 是取查询条件进行分词之后查询条间的并集还是交集【0:代表并集,1:代表交集】
*/
public List<Map<String , Object>> matchQuery(String index, int page, int size, String field, Object value, int operator) {
List<Map<String, Object>> list = new ArrayList<>();
SearchRequest request = new SearchRequest(index);
SearchSourceBuilder builder = new SearchSourceBuilder();
MatchQueryBuilder matchQuery = QueryBuilders.matchQuery(field, value);
if (operator == 1){
matchQuery.operator(Operator.AND);
}
builder.query(matchQuery).from((page-1)*size).size(size);
request.source(builder);
try {
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
Map<String, Object> source = hit.getSourceAsMap();
list.add(source);
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
/**
* 精准查询
*
* @param index 索引
* @param page 当前页
* @param size 页大小
* @param field 查询字段
* @param value 字段查询条件
*/
public List<Map<String, Object>> termQuery(String index, int page, int size , String field , Object value) {
List<Map<String, Object>> list = new ArrayList<>();
SearchRequest request = new SearchRequest(index);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.termQuery(field,value)).from((page-1)*size).size(size);
request.source(builder);
try {
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
Map<String, Object> source = hit.getSourceAsMap();
list.add(source);
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
/**
* 范围查询
*
* @param index 索引
* @param page 当前页
* @param size 页大小
* @param field 查询字段
* @param gte 最小值
* @param lte 最大值
*/
public List<Map<String, Object>> rangeQuery(String index, int page, int size, String field, Object gte, Object lte) {
List<Map<String, Object>> list = new ArrayList<>();
SearchRequest request = new SearchRequest(index);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.rangeQuery(field).gte(gte).lte(lte)).from((page-1)*size).size(size);
request.source(builder);
try {
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
Map<String, Object> source = hit.getSourceAsMap();
list.add(source);
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
/**
* 模糊查询 查询以“张“开头的则为”张*“
*
* @param index 索引
* @param page 当前页
* @param size 页大小
* @param field 查询字段
* @param value 条件
*/
public List<Map<String, Object>> wildcardQuery(String index, int page, int size, String field, String value) {
List<Map<String, Object>> list = new ArrayList<>();
SearchRequest request = new SearchRequest(index);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.wildcardQuery(field,value)).from((page-1)*size).size(size);
request.source(builder);
try {
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
Map<String, Object> source = hit.getSourceAsMap();
list.add(source);
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
/**
* 降序排序
*
* @param index 索引
* @param page 当前页
* @param size 页大小
* @param field 查询字段
*/
public List<Map<String, Object>> sortQuery(String index, int page, int size, String field) {
List<Map<String, Object>> list = new ArrayList<>();
SearchRequest request = new SearchRequest(index);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery()).from((page-1)*size).size(size);
builder.sort(field, SortOrder.DESC);
request.source(builder);
try {
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
Map<String, Object> source = hit.getSourceAsMap();
list.add(source);
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
public List<Map<String , Object>> boolQuery(String index, int page, int size) {
List<Map<String, Object>> list = new ArrayList<>();
SearchRequest request = new SearchRequest(index);
SearchSourceBuilder builder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.must().add(QueryBuilders.matchQuery("title","华为手机"));
boolQuery.must().add(QueryBuilders.rangeQuery("price").gte(2000D).lte(3000D));
builder.query(boolQuery).from((page-1)*size).size(size);
request.source(builder);
try {
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
Map<String, Object> source = hit.getSourceAsMap();
list.add(source);
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
/**
* 高亮显示某字段
*
* @param index 索引
* @param page 当前页
* @param size 页大小
* @param field 查询字段
* @param value 查询条件
*/
public List<Map<String, Object>> highLightQuery(String index, int page, int size, String field ,String value) {
List<Map<String, Object>> list = new ArrayList<>();
SearchRequest searchRequest = new SearchRequest(index);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(field, value);
searchSourceBuilder.query(termQueryBuilder).from((page-1)*size).size(size);
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags("");
highlightBuilder.postTags("");
highlightBuilder.field(field);
searchSourceBuilder.highlighter(highlightBuilder);
searchRequest.source(searchSourceBuilder);
try {
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
hits.forEach(hit -> {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String title = hit.getHighlightFields().get(field).getFragments()[0].toString();
sourceAsMap.put("title" , title);
list.add(sourceAsMap);
});
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
}
package com.qq.es;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author 黔程似景
* @description 启动类
* @date 2023/6/17 11:45
* @blame 黔程似景
**/
@SpringBootApplication
public class ApplicationStarter {
public static void main(String[] args) {
SpringApplication.run(ApplicationStarter.class , args);
}
}
package com.qq.es.test.service.impl;
import com.qq.es.service.RestHighLevelService;
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.List;
import java.util.Map;
/**
* @author 黔程似景
* @description
* @date 2023/6/17 12:24
* @blame 黔程似景
**/
@SpringBootTest
@RunWith(SpringRunner.class)
public class RestHighLevelServiceImplTest {
@Autowired
private RestHighLevelService restHighLevelService;
@Test
public void test_addDoc() {
Map<String, Object> data = new HashMap<>();
data.put("name" , "qian黔景");
data.put("age" , "20");
String doc = restHighLevelService.addOrUpdateDoc("qianjing", "-geezogB5XfR_FCc1ea9", data);
System.out.println(doc);
}
/**
* 其实没有mapping也是可以生成文档的。
* @throws IOException
*/
@Test
public void test_createMappingIndex() {
String source = "{\n" +
" \"properties\": {\n" +
" \"name\":{\n" +
" \"type\": \"text\"\n" +
" },\n" +
" \"age\":{\n" +
" \"type\": \"integer\"\n" +
" }\n" +
" }\n" +
" }";
boolean result = restHighLevelService.createIndex("qianjing", source);
System.out.println(result);
}
@Test
public void test_matchAll() {
List<Map<String, Object>> goods = restHighLevelService.matchAllQuery("goods" , 1 , 20);
goods.forEach(System.out::println);
}
@Test
public void test_sortQuery() {
List<Map<String, Object>> goods = restHighLevelService.sortQuery("goods" , 1 , 20 , "price");
goods.forEach(System.out::println);
}
@Test
public void testHighlight() {
List<Map<String, Object>> list = restHighLevelService.highLightQuery("goods" , 1 , 20 , "title" , "联通");
for (Map<String, Object> map : list) {
System.out.println(map);
}
}
@Test
public void testBoolQuery() {
List<Map<String, Object>> list = restHighLevelService.boolQuery("goods" , 1 , 20);
for (Map<String, Object> map : list) {
System.out.println(map);
}
}
}