【Elasticsearch】检索排序 & 分页

检索排序 & 分页

1.测试数据准备

首先,我们创建一个名为 blog_posts 的索引,并插入一些测试数据:

json 复制代码
PUT /blog_posts
{
  "mappings": {
    "properties": {
      "title": { "type": "text" },
      "content": { "type": "text" },
      "author": { "type": "keyword" },
      "views": { "type": "integer" },
      "publish_date": { "type": "date" },
      "tags": { "type": "keyword" }
    }
  }
}
json 复制代码
POST /blog_posts/_bulk
{"index":{}}
{"title":"Elasticsearch Basics","content":"Learn the basics of Elasticsearch and how to perform simple queries.","author":"John Doe","views":1500,"publish_date":"2023-01-15","tags":["search","database"]}
{"index":{}}
{"title":"Advanced Search Techniques","content":"Explore advanced search techniques in Elasticsearch including aggregations and filters.","author":"Jane Smith","views":3200,"publish_date":"2023-02-20","tags":["search","advanced"]}
{"index":{}}
{"title":"Data Analytics with ELK","content":"How to use the ELK stack for data analytics and visualization.","author":"John Doe","views":2800,"publish_date":"2023-03-10","tags":["analytics","elk"]}
{"index":{}}
{"title":"Elasticsearch Performance Tuning","content":"Tips and tricks for optimizing Elasticsearch performance in production environments.","author":"Mike Johnson","views":4200,"publish_date":"2023-04-05","tags":["performance","optimization"]}
{"index":{}}
{"title":"Kibana Dashboard Guide","content":"Creating effective dashboards in Kibana for monitoring and analysis.","author":"Jane Smith","views":1900,"publish_date":"2023-05-12","tags":["kibana","visualization"]}

2.排序功能

能排序的字段都具备正排索引,单 text 类型字段是不可以排序的。如果要使 text 字段支持排序、聚合,则需要开启 fielddata

sort 是和 query 平级的,并不会被 query 包含。

2.1 简单字段排序

json 复制代码
GET /blog_posts/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "views": {
        "order": "desc"
      }
    }
  ]
}

2.2 多字段排序

json 复制代码
GET /blog_posts/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "author": {
        "order": "asc"
      }
    },
    {
      "views": {
        "order": "desc"
      }
    }
  ]
}

2.3 日期排序

json 复制代码
GET /blog_posts/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "publish_date": {
        "order": "desc"
      }
    }
  ]
}

3.分页功能

Elasticsearch 支持对查询结果进行分页处理,允许用户逐步获取和浏览大量数据。

在编写查询语句时,可通过再请求体中添加 fromsize 字段实现分页。from 表示结果集的起始位置,而 size 表示每页返回的文档数量。

如果将 from 设置为 11 11 11,size 设置为 5 5 5,则返回的是第 10 10 10 ~ 14 14 14 条数据(默认从第 0 0 0 条开始)。

3.1 基础分页

json 复制代码
GET /blog_posts/_search
{
  "query": {
    "match_all": {}
  },
  "from": 0,
  "size": 2,
  "sort": [
    {
      "publish_date": {
        "order": "desc"
      }
    }
  ]
}

3.2 深度分页(不推荐大数据量使用)

深度分页 指的是在 Elasticsearch 中查询结果集 非常靠后的页码(例如第 1000 1000 1000 页,每页 10 10 10 条数据,即 from=10000)。它通常表现为使用 from + size 参数组合来获取远端的分页数据。

❌ 不推荐的详细原因可参考我的另一篇博客:《【Elasticsearch】深度分页及其替代方案》。

当然,我们这里测试的数据没有那么多。

json 复制代码
GET /blog_posts/_search
{
  "query": {
    "match_all": {}
  },
  "from": 3,
  "size": 2
}

3.3 使用 search_after 进行高效分页

首先获取第一页:

json 复制代码
GET /blog_posts/_search
{
  "query": {
    "match_all": {}
  },
  "size": 2,
  "sort": [
    {
      "views": {
        "order": "desc"
      }
    },
    {
      "_id": {
        "order": "asc"
      }
    }
  ]
}

然后使用最后一个结果的排序值获取下一页:

json 复制代码
GET /blog_posts/_search
{
  "query": {
    "match_all": {}
  },
  "size": 2,
  "search_after": [3200, "上一页最后一个文档的ID"],
  "sort": [
    {
      "views": {
        "order": "desc"
      }
    },
    {
      "_id": {
        "order": "asc"
      }
    }
  ]
}


4.综合示例:高亮+排序+分页

json 复制代码
GET /blog_posts/_search
{
  "query": {
    "multi_match": {
      "query": "search",
      "fields": ["title", "content"]
    }
  },
  "highlight": {
    "fields": {
      "title": {},
      "content": {
        "fragment_size": 100,
        "number_of_fragments": 2
      }
    }
  },
  "sort": [
    {
      "views": {
        "order": "desc"
      }
    }
  ],
  "from": 0,
  "size": 3
}

5.实践建议

功能 实践建议
高亮 * 对于大文本字段,限制 fragment_sizenumber_of_fragments 以提高性能。 * 考虑使用 require_field_match: true 来只高亮查询中指定的字段。
排序 * 对于文本字段排序,使用 .keyword 子字段或设置 fielddata: true。 * 避免对未索引或分析的字段进行排序。 * 对于分页场景,使用包含唯一值的排序条件(如 _id)。
分页 * 避免深度分页(超过 1000 1000 1000 条记录)),使用 search_after 代替。 * 对于无限滚动等场景,优先考虑 search_after 而不是 from/size。 * 考虑使用滚动 API(Scroll API)对于大数据量导出场景。
相关推荐
洛森唛6 小时前
Elasticsearch DSL 查询语法大全:从入门到精通
后端·elasticsearch
字节跳动数据平台11 小时前
代码量减少 70%、GPU 利用率达 95%:火山引擎多模态数据湖如何释放模思智能的算法生产力
大数据
得物技术12 小时前
深入剖析Spark UI界面:参数与界面详解|得物技术
大数据·后端·spark
武子康13 小时前
大数据-238 离线数仓 - 广告业务 Hive分析实战:ADS 点击率、购买率与 Top100 排名避坑
大数据·后端·apache hive
武子康1 天前
大数据-237 离线数仓 - Hive 广告业务实战:ODS→DWD 事件解析、广告明细与转化分析落地
大数据·后端·apache hive
大大大大晴天2 天前
Flink生产问题排障-Kryo serializer scala extensions are not available
大数据·flink
Elasticsearch2 天前
如何使用 Agent Builder 排查 Kubernetes Pod 重启和 OOMKilled 事件
elasticsearch
Elasticsearch3 天前
通用表达式语言 ( CEL ): CEL 输入如何改进 Elastic Agent 集成中的数据收集
elasticsearch
武子康4 天前
大数据-236 离线数仓 - 会员指标验证、DataX 导出与广告业务 ODS/DWD/ADS 全流程
大数据·后端·apache hive
武子康5 天前
大数据-235 离线数仓 - 实战:Flume+HDFS+Hive 搭建 ODS/DWD/DWS/ADS 会员分析链路
大数据·后端·apache hive