ElasticSearch JavaRestClient查询之排序和分页

发布于:2025-04-04 ⋅ 阅读:(19) ⋅ 点赞:(0)

一、核心API结构

通过SearchRequest.source()设置查询条件、分页参数和排序参数,三者属于同一级别:

SearchRequest request = new SearchRequest("index");
request.source()
    .query(...)        // 设置查询条件
    .from(...)         // 设置分页起始位置
    .size(...)         // 设置每页大小
    .sort(...);        // 设置排序条件

二、分页功能实现

1. 分页参数转换

前端参数 -> ES参数

  • pageNumber(页码) -> from
  • pageSize(每页大小) -> size

转换公式

int from = (pageNumber - 1) * pageSize;
int size = pageSize;

2. 代码实现示例

// 模拟前端传递参数
int pageNumber = 1;    // 当前页码
int pageSize = 5;      // 每页大小

// 设置分页
request.source()
    .from((pageNumber - 1) * pageSize)
    .size(pageSize);

三、排序功能实现

1. 单字段排序

// 按销量降序排序
request.source().sort("sales", SortOrder.DESC);

2. 多字段排序

// 主排序:销量降序,次排序:价格升序
request.source()
    .sort("sales", SortOrder.DESC)
    .sort("price", SortOrder.ASC);

3. 排序参数说明

  • SortOrder 枚举:
    • ASC:升序(默认)
    • DESC:降序

四、完整案例实现

需求说明:

  1. 查询所有数据
  2. 分页显示(第1页,每页5条)
  3. 主排序:库存降序
  4. 次排序:价格升序

Java代码实现

@Test
void testSortAndPage() throws IOException {
// 1. 创建请求对象
SearchRequest request = new SearchRequest("items");

// 2. 设置查询条件(查所有)
request.source().query(QueryBuilders.matchAllQuery());

// 3. 设置分页参数
int pageNumber = 1;
int pageSize = 5;
request.source()
.from((pageNumber - 1) * pageSize)
.size(pageSize);

// 4. 设置排序条件
request.source()
.sort("stock", SortOrder.DESC)  // 库存降序
.sort("price", SortOrder.ASC);  // 价格升序

// 5. 发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);

// 6. 解析结果
parseResponse(response);
}

// 封装结果解析方法
private void parseResponse(SearchResponse response) {
    SearchHits hits = response.getHits();
    System.out.println("共查询到 " + hits.getTotalHits().value + " 条数据");

    for (SearchHit hit : hits.getHits()) {
        String json = hit.getSourceAsString();
        ItemDoc doc = JSONUtil.toBean(json, ItemDoc.class);

        System.out.println("doc = " + doc);
    }
}

运行结果:

五、实际应用建议

1. 分页优化

  • 深度分页问题:避免使用超过1000页的深度分页(ES默认限制10000条)
  • 滚动查询:大数据量分页推荐使用scroll API

2. 排序扩展

  • 地理排序:sort(new GeoDistanceSortBuilder("location").point(lat, lon))
  • 脚本排序:.sort(SortBuilders.scriptSort(...))

3. 参数校验

// 校验分页参数有效性
if(pageNumber < 1) throw new IllegalArgumentException("页码不能小于1");
if(pageSize > 100) throw new IllegalArgumentException("单页大小不能超过100");

六、常见问题排查

1. 排序不生效

  • 检查字段类型:text类型字段需要改用keyword类型排序
  • 检查字段是否存在:确认索引映射包含排序字段

2. 分页数据重复

  • 确保排序字段组合能唯一确定顺序(建议包含_id字段)

3. 性能优化

  • 对常用排序字段设置doc_values: true
  • 避免在分页查询中使用高开销排序(如脚本排序)