SpringBoot 集成ElasticSearch(二)分页查询

SpringBoot 集成ElasticSearch 之分页查询

       SpringBoot 集成ElasticSearch 的代码,我在上一篇博客中已经写过,这边就不重复了。主要记录下service层实现类中分页查询的方法
       实体类、配置信息以及新增、更新的代码在上一篇博客中,地址:

SpringBoot 集成ElasticSearch

       我在网上找了几种方法,我这里暂时只记录其中两种查询方式,第一种是几乎原生的API,第二种是经过spring二次封装的;两种方式都能查询成功

注 :两种方式的 page 都是从 0 开始,我这里是做了减一处理的

第一种

导包

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;

代码

@Qualifier("client")
@Autowired
private RestHighLevelClient restHighLevelClient;

@Override
public Map<String,Object> query(Map<String,Object> datasMap) throws IOException {
	// 参数定义
	String datas = String.valueOf(datasMap.get("datas"));
	String deviceMac = String.valueOf(datasMap.get("deviceMac"));
	String deviceSn = String.valueOf(datasMap.get("deviceSn"));
	String deviceTypes = String.valueOf(datasMap.get("deviceTypes"));
	String createDateStart = String.valueOf(datasMap.get("createDateStart"));
	String createDateEnd = String.valueOf(datasMap.get("createDateEnd"));
	// 分页参数
	String order = String.valueOf(datasMap.get("order"));
	String orderColumn = String.valueOf(datasMap.get("orderColumn"));
	Integer page = datasMap.get("pageNum") != null ? Integer.valueOf(String.valueOf(datasMap.get("pageNum"))) : 1;
	Integer size = datasMap.get("pageSize") != null ? Integer.valueOf(String.valueOf(datasMap.get("pageSize"))) : 10;

	
	List<String> deviceTypeList = null;
	if(StringUtils.isNotBlank(deviceTypes) && !(deviceTypes.equalsIgnoreCase("null"))) {
		deviceTypeList = Arrays.asList(deviceTypes.split(","));
	}
	
	// 封装查询条件
	BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
	// 多字段查询 
	BoolQueryBuilder multiBuilder = new BoolQueryBuilder();
	// 多值查询
	BoolQueryBuilder termsBuilder = new BoolQueryBuilder();
	// 模糊查询
	BoolQueryBuilder matchBuilder = new BoolQueryBuilder();
	// 精确查询
	BoolQueryBuilder termBuilder = new BoolQueryBuilder();
       
       if(StringUtils.isNotBlank(datas) && !(datas.equalsIgnoreCase("null"))) {
       	// 在discusspost索引的datas和deviceMac字段中都查询 datas 
       	multiBuilder.should(QueryBuilders.multiMatchQuery(datas, "datas", "deviceMac"));
       	queryBuilder.must(multiBuilder);
       }
       
       if(deviceTypeList != null && deviceTypeList.size() > 0) {
       	// 在discusspost索引的deviceType字段中都查询多个值
       	termsBuilder.should(QueryBuilders.termsQuery("deviceType",deviceTypeList));
       	queryBuilder.must(termsBuilder);
       }
       
       if(StringUtils.isNotBlank(deviceMac) && !(deviceMac.equalsIgnoreCase("null"))) {
       	// 模糊查询
       	matchBuilder.should(QueryBuilders.matchQuery("deviceMac",deviceMac));
       	queryBuilder.must(matchBuilder);
       }
       
       if(StringUtils.isNotBlank(deviceSn) && !(deviceSn.equalsIgnoreCase("null"))) {
       	// 精准查询
       	termBuilder.should(QueryBuilders.termQuery("deviceSn",deviceSn));
       	queryBuilder.must(termBuilder);
       }
       
       // 时间范围筛选
	if (StringUtils.isNotBlank(createDateStart) && StringUtils.isNotBlank(createDateEnd)
	  		&& !(createDateStart.equalsIgnoreCase("null")) && !(createDateEnd.equalsIgnoreCase("null"))){
	  
		queryBuilder
			.filter(QueryBuilders.rangeQuery("createDate")
					.gte(DateUtil.parseStrToDate(createDateStart,DateUtil.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS))
					.lte(DateUtil.parseStrToDate(createDateEnd,DateUtil.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS)));
	}
	
	// 构建搜索条件
     SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
             .sort(SortBuilders.fieldSort(orderColumn).order(SortOrder.fromString(order)))
             // 一个可选项,用于控制允许搜索的时间:searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
             // 查询条件
             .query(queryBuilder)
             .from((page - 1) * size) // 指定从哪条开始查询 从0开始计算 第一页是 0
             .size(size); // 需要查出的总记录条数
	
	// discusspost是索引名
	SearchRequest searchRequest = new SearchRequest("discusspost");
	searchRequest.source(searchSourceBuilder);
	SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

	List<DatasEntity> list = new LinkedList<>();
	
	for (SearchHit hit : searchResponse.getHits().getHits()) {
		DatasEntity discussPost = JSONObject.parseObject(hit.getSourceAsString(), DatasEntity.class);
		list.add(discussPost);
	}
	
	// 返回参数
	Map<String,Object> map = new HashMap<>();
	
	map.put("data", list);
	map.put("page", page);
	map.put("size", size);
	map.put("total", searchResponse.getHits().getTotalHits().value);
	return map;
}
postman测试

在这里插入图片描述

第二种

service层

导包

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Service;

代码

@Autowired
private DatasMapper datasMapper;

@Override
public Map<String,Object> query(Map<String,Object> datasMap) throws IOException {
	
	// 参数定义
	String datas = String.valueOf(datasMap.get("datas"));
	String deviceTypes = String.valueOf(datasMap.get("deviceTypes"));
	String createDateStart = String.valueOf(datasMap.get("createDateStart"));
	String createDateEnd = String.valueOf(datasMap.get("createDateEnd"));
	// 分页参数
	String order = String.valueOf(datasMap.get("order"));
	String orderColumn = String.valueOf(datasMap.get("orderColumn"));
	Integer page = datasMap.get("page") != null ? Integer.valueOf(String.valueOf(datasMap.get("page"))) : 1;
	Integer size = datasMap.get("size") != null ? Integer.valueOf(String.valueOf(datasMap.get("size"))) : 10;

	List<String> deviceTypeList = null;
	if(StringUtils.isNotBlank(deviceTypes) && !(deviceTypes.equalsIgnoreCase("null"))) {
		deviceTypeList = Arrays.asList(deviceTypes.split(","));
	}
	
	// 查询对象
	BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
	// 模糊搜索对象
	BoolQueryBuilder keyBuilder = new BoolQueryBuilder();
	// 分类查询对象
	BoolQueryBuilder orBuilder = new BoolQueryBuilder();
	
	// 拼接模糊搜索条件
	if (StringUtils.isNotBlank(datas) && !(datas.equalsIgnoreCase("null"))){
	    // 这边主要用的是should,也就是相当于mysql的or   datas like concat('%datas%') or deviceMac like concat('%datas%') 
	    // wildcardQuery可以用于带分词的模糊搜索,如果要分词的话,那么字段的type应该是text,假如在用wildcardQuery而不想分词的话,可以查.keyword
	    // 例如title.keyword,不过我这边title的type已经定了是keyword类型,所以我就直接做不分词的模糊查询,精确查询的话就用matchQuery
	    keyBuilder.should(QueryBuilders.wildcardQuery("datas", "*" + datas + "*"));
	    keyBuilder.should(QueryBuilders.wildcardQuery("deviceMac", "*" + datas + "*"));
	    queryBuilder.must(keyBuilder);
	}
	
	// 拼接分类筛选条件
	if (deviceTypeList != null && deviceTypeList.size() > 0){
	    // 这里主要是实现了多条件筛选的需求,前端有复选框的条件筛选,后端以集合方式接收,然后做or的条件拼接 deviceType = '1' or deviceType = '2'...
		deviceTypeList.forEach(s -> orBuilder.should(QueryBuilders.matchQuery("deviceType",s)));
	    queryBuilder.must(orBuilder);
	}
	
	// 时间范围筛选
	if (StringUtils.isNotBlank(createDateStart) && StringUtils.isNotBlank(createDateEnd)
			&& !(createDateStart.equalsIgnoreCase("null")) && !(createDateEnd.equalsIgnoreCase("null"))){
	    // 范围筛选就用rangeQuery 相当于 >= 'xx' and <= 'xx'   还有gt方法和lt方法就是不带 '='
	    QueryBuilder queryRange = QueryBuilders.rangeQuery("createDate")
	            .gte(DateUtil.parseStrToDate(createDateStart,DateUtil.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS))
	            .lte(DateUtil.parseStrToDate(createDateEnd,DateUtil.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS));
	    queryBuilder.filter(queryRange);
	}
	// 分页查询并按发布时间排序
	// 这边的分页只能算是form-size的浅层分页,如果数据量大的话,建议改造成scroll深度分页
	// 这里 page 要减一
	Pageable pageable = PageRequest.of(page - 1, size, Direction.fromString(order),orderColumn);
	Page<DatasEntity> search = datasMapper.search(queryBuilder,pageable);
	
	Map<String ,Object> map = new HashMap<>();
	map.put("data", search);
	return map;
}
Dao层

导包

import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Component;

代码

@Component
public interface DatasMapper extends ElasticsearchRepository<DatasEntity,Long>  {
}
postman测试

在这里插入图片描述
参考博客:

https://blog.csdn.net/wpw2000/article/details/115704320
https://www.jb51.net/article/211278.htm
https://blog.csdn.net/weixin_45566249/article/details/111297868
https://blog.csdn.net/BiandanLoveyou/article/details/115874372
https://www.jianshu.com/p/86afb2d3bd27

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot中集成Elasticsearch并实现分页,你可以按照以下步骤操作: 1. 首先,确保已经添加了Elasticsearch的依赖。在你的pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> ``` 2. 创建一个Elasticsearch配置类,用于配置Elasticsearch的连接信息。可以参考下面的示例代码: ```java @Configuration @EnableElasticsearchRepositories(basePackages = "com.example.repository") public class ElasticsearchConfig { @Value("${elasticsearch.host}") private String host; @Value("${elasticsearch.port}") private int port; @Value("${elasticsearch.clustername}") private String clusterName; @Bean public Client client() throws Exception { Settings settings = Settings.builder() .put("cluster.name", clusterName) .build(); TransportClient client = new PreBuiltTransportClient(settings); client.addTransportAddress(new TransportAddress(InetAddress.getByName(host), port)); return client; } @Bean public ElasticsearchOperations elasticsearchTemplate() throws Exception { return new ElasticsearchTemplate(client()); } } ``` 3. 创建一个Elasticsearch实体类,用于映射索引中的文档。例如,假设你有一个名为"User"的索引,可以创建一个名为"User"的实体类,包含需要存储的字段及对应的注解。示例代码如下: ```java @Document(indexName = "user_index", type = "user") public class User { @Id private String id; @Field(type = FieldType.Keyword) private String name; // getters and setters } ``` 4. 创建一个Elasticsearch的Repository接口,用于执行查询操作。示例代码如下: ```java @Repository public interface UserRepository extends ElasticsearchRepository<User, String> { Page<User> findByName(String name, Pageable pageable); } ``` 5. 在你的服务类或控制器中注入UserRepository,并使用其提供的方法进行分页查询。示例代码如下: ```java @Service public class UserService { @Autowired private UserRepository userRepository; public Page<User> searchUsersByName(String name, int page, int size) { Pageable pageable = PageRequest.of(page, size); return userRepository.findByName(name, pageable); } } ``` 这样,你就可以在Spring Boot中集成Elasticsearch并实现分页查询了。你可以根据实际需求进行适当的调整和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值