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

}

相关推荐
深兰科技5 小时前
深兰科技法务大模型亮相,推动律所文书处理智能化
人工智能·scrapy·beautifulsoup·scikit-learn·pyqt·fastapi·深兰科技
叶子丶苏3 天前
第八节_PySide6基本窗口控件_按钮类控件(QAbstractButton)
python·pyqt
龙腾AI白云3 天前
大模型-7种大模型微调方法 上
scrapy·scikit-learn·pyqt
开心-开心急了4 天前
PySide6 使用搜索引擎搜索 多类实现 更新1次
python·pyqt·pyside
herbal_medicine4 天前
【测试】123456789
pyqt
懷淰メ6 天前
python3GUI--模仿百度网盘的本地文件管理器 By:PyQt5(详细分享)
开发语言·python·pyqt·文件管理·百度云·百度网盘·ui设计
失心疯_20237 天前
PyQt开发_小学学习辅助工具
学习·pyqt
宝贝儿好11 天前
【python】第五章:python-GUI编程
python·pyqt
Goona_12 天前
PyQt批量年龄计算工具:从身份证到指定日期的周岁处理
python·小程序·交互·pyqt
AI视觉网奇13 天前
pyqt 触摸屏监听
开发语言·python·pyqt