es分页查询最新

import org.apache.http.HttpHost;

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.builder.SearchSourceBuilder;

import org.elasticsearch.search.sort.SortOrder;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

import java.util.Map;

public class ElasticsearchSearchAfterExample {

复制代码
private final RestHighLevelClient client;

public ElasticsearchSearchAfterExample(RestHighLevelClient client) {
    this.client = client;
}

/**
 * 使用 search_after 实现分页查询,并每次都重新请求总文档数。
 *
 * @param indexName 索引名称
 * @param pageSize  每页大小
 * @param sortField 排序字段
 * @param pageNum   页码 (从1开始)
 * @param queryMap  查询条件映射
 * @return 包含当前页文档列表和总文档数的 Map
 */
public Map<String, Object> paginateWithSearchAfter(String indexName, int pageSize, String sortField, int pageNum, Map<String, Object> queryMap) throws IOException {
    List<Map<String, Object>> pageDocs = new ArrayList<>();
    Long totalHits = null;

    // 构建查询对象
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    sourceBuilder.query(buildQueryFromMap(queryMap));
    sourceBuilder.size(pageSize);
    sourceBuilder.sort(sortField, SortOrder.ASC);

    // 先获取总文档数
    SearchRequest countRequest = new SearchRequest(indexName);
    SearchSourceBuilder countSourceBuilder = new SearchSourceBuilder();
    countSourceBuilder.query(buildQueryFromMap(queryMap));
    countSourceBuilder.size(0); // 只关心总数,不需要返回具体文档
    countSourceBuilder.trackTotalHits(true); // 确保跟踪总命中数

    countRequest.source(countSourceBuilder);
    SearchResponse countResponse = client.search(countRequest, RequestOptions.DEFAULT);
    totalHits = countResponse.getHits().getTotalHits().value;

    // 构建分页查询请求
    SearchRequest searchRequest = new SearchRequest(indexName);
    searchRequest.source(sourceBuilder);

    // 如果不是第一页,则需要设置 search_after 参数
    if (pageNum > 1) {
        // 获取上一页最后一个文档的排序值,用于构建 search_after 请求
        // 注意:这里简化了处理,实际应用中需要根据具体情况实现
        // 这里假设有一个方法 getLastSortValues 来获取这些值
        List<Object> lastSortValues = getLastSortValues(pageNum - 1, indexName, pageSize, sortField, queryMap);
        if (lastSortValues != null && !lastSortValues.isEmpty()) {
            sourceBuilder.searchAfter(lastSortValues.toArray(new Object[0]));
        }
    }

    SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

    for (SearchHit hit : searchResponse.getHits()) {
        pageDocs.add(hit.getSourceAsMap());
    }

    // 返回包含文档列表和总文档数的结果
    return Map.of("docs", pageDocs, "totalHits", totalHits);
}

/**
 * 根据查询条件映射构建查询对象。
 */
private org.elasticsearch.index.query.QueryBuilder buildQueryFromMap(Map<String, Object> queryMap) {
    // 示例:假设你有一个名为 "field" 的查询参数用于匹配特定字段
    if (queryMap == null || queryMap.isEmpty()) {
        return QueryBuilders.matchAllQuery();
    }
    return QueryBuilders.termQuery((String) queryMap.getOrDefault("field", ""), queryMap.getOrDefault("value", ""));
}

/**
 * 获取指定页码前一页最后一个文档的排序值。
 */
private List<Object> getLastSortValues(int pageNum, String indexName, int pageSize, String sortField, Map<String, Object> queryMap) throws IOException {
    // 这是一个简化的例子,实际应用中可能需要更复杂的逻辑来获取正确的排序值
    // 这里假设只需要取最后一条记录的排序值作为 search_after 的参数

    SearchRequest searchRequest = new SearchRequest(indexName);
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    sourceBuilder.query(buildQueryFromMap(queryMap));
    sourceBuilder.size(1);
    sourceBuilder.sort(sortField, SortOrder.DESC); // 按降序排列以获取最后一条记录

    if (pageNum > 1) {
        // 计算实际需要跳过的文档数量并遍历到正确的起始位置...
        // (这部分代码与之前的例子相同)
        int skipDocs = (pageNum - 1) * pageSize;
        sourceBuilder.from(skipDocs);
    }

    searchRequest.source(sourceBuilder);
    SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

    if (!searchResponse.getHits().getHits().isEmpty()) {
        SearchHit lastHit = searchResponse.getHits().getHits()[0];
        return List.of(lastHit.getSortValues());
    }

    return null;
}

public static void main(String[] args) throws IOException {
    try (RestHighLevelClient client = new RestHighLevelClient(
            RestClient.builder(new HttpHost("localhost", 9200, "http")))) {

        ElasticsearchSearchAfterExample example = new ElasticsearchSearchAfterExample(client);
        
        // 获取第1页的数据及总数,带查询参数
        Map<String, Object> queryMap = Map.of("field", "status", "value", "active");
        Map<String, Object> resultPage1 = example.paginateWithSearchAfter("my-index-000001", 10, "timestamp", 1, queryMap);
        System.out.println("Documents on Page 1: " + resultPage1.get("docs"));
        System.out.println("Total Hits: " + resultPage1.get("totalHits"));

        // 获取第2页的数据及总数,带相同的查询参数
        Map<String, Object> resultPage2 = example.paginateWithSearchAfter("my-index-000001", 10, "timestamp", 2, queryMap);
        System.out.println("Documents on Page 2: " + resultPage2.get("docs"));
        System.out.println("Total Hits: " + resultPage2.get("totalHits"));

        // 获取第1页的数据及总数,带不同查询参数
        Map<String, Object> queryMap2 = Map.of("field", "status", "value", "inactive");
        Map<String, Object> resultPage1Inactive = example.paginateWithSearchAfter("my-index-000001", 10, "timestamp", 1, queryMap2);
        System.out.println("Documents on Page 1 (Inactive): " + resultPage1Inactive.get("docs"));
        System.out.println("Total Hits (Inactive): " + resultPage1Inactive.get("totalHits"));
    }
}

}

相关推荐
MoRanzhi12032 小时前
第6篇(下)· 使用 PyQt5 实现 2048 高性能计算版:统一运行控制与跨模式安全交接
python·pyqt·进程管理·状态机·软件架构·并发控制·数据一致性
wuyk5552 天前
PyQt6-第06讲-主窗口框架
python·pyqt
MoRanzhi12032 天前
第6篇(中)· 使用 PyQt5 实现 2048 高性能计算版:无头后台求解与三档运行模式
python·pyqt·数据持久化·多进程·进程间通讯·后台任务·断点续跑
wuyk5557 天前
PyQt6-第05讲-QtDesigner工作流与ui文件
python·ui·pyqt
金融小师妹7 天前
多因子时间序列分析:美元与美债收益率变化对黄金价格+1.6%的影响
c语言·人工智能·git·决策树·pyqt
金融小师妹8 天前
事件驱动分析模型:9月PPI超预期与美联储利率预期对黄金价格的影响
人工智能·云计算·线性回归·pyqt
zx_7414848112 天前
PyQt5 环境搭建保姆级教程:PyCharm + QtDesigner + PyUIC 完整配置
开发语言·qt·pycharm·pyqt
zhanghaha13141 个月前
Python进阶教程:35_PyQt (保姆级零基础教程)
开发语言·python·pyqt
线上放牧人1 个月前
Windows删除图标缓存
windows·python·pyqt
典典分享指南1 个月前
用飞书 Wiki 搭内容作战室:从零搭建团队内容协作中枢
django·flask·numpy·pyqt