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

}

相关推荐
蹦蹦跳跳真可爱5894 天前
Python----PyQt开发(PyQt高级:手搓一个音乐播放器)
python·pyqt
mosquito_lover110 天前
怎么把pyqt界面做的像web一样漂亮
前端·python·pyqt
薛尧笔记13 天前
关于FSGithubPNG生成外链时描述出现路径问题
笔记·python·github·pyqt·桌面应用
蹦蹦跳跳真可爱58913 天前
Python----PyQt开发(PyQt高级:手搓一个简单的记事本)
python·pyqt
深蓝海拓14 天前
PySide(PyQT)使用场景(QGraphicsScene)进行动态标注的一个demo
开发语言·python·pyqt
#岩王爷15 天前
cv2小练习
音视频·pyqt
不知名君15 天前
PyQt组态软件 拖拽设计界面测试
python·pyqt·qt5
XS3015 天前
PyQt学习记录03——批量设置水印
学习·pyqt
蹦蹦跳跳真可爱58916 天前
Python----PyQt开发(PyQt基础,环境搭建,Pycharm中PyQttools工具配置,第一个PyQt程序)
开发语言·python·pyqt
蹦蹦跳跳真可爱58916 天前
Python----PyQt开发(PyQt高级:组件大小,界面位置,按钮,文本显示,文本输入,字体大小)
python·pyqt