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"));
    }
}

}

相关推荐
深蓝海拓4 天前
PySide6(PyQT5)的QMessageBox获取被点击按钮的三种方法
开发语言·python·qt·pyqt
飞行codes5 天前
pyqt鸟瞰
pyqt
shanks668 天前
【PyQt】通过load ui来实现菜单栏
ui·pyqt
恋恋西风8 天前
Python PyQt 子类中回调主类的函数,回调
python·pyqt
深蓝海拓9 天前
基于深度学习的视觉检测小项目(十二) 使用线条边框和渐变颜色美化界面
前端·python·pyqt
深蓝海拓11 天前
基于深度学习的视觉检测小项目(十一) 动态样式表的实践
前端·python·pyqt
大学生毕业题目14 天前
毕业项目推荐:基于yolov8/yolov5/yolo11的动物检测识别系统(python+卷积神经网络)
人工智能·python·深度学习·yolo·cnn·pyqt
麦田里的稻草人w14 天前
【pyqt】(八)ui文件使用
python·ui·pyqt
深蓝海拓15 天前
PySide6的样式表
python·pyqt
深蓝海拓17 天前
基于深度学习的视觉检测小项目(六) 项目的信号和变量的规划
pytorch·深度学习·yolo·视觉检测·pyqt