排序与分页 #

一、排序 #

1.1 基本排序 #

bash
# 单字段排序
curl "http://localhost:8983/solr/mycore/select?q=*:*&sort=price desc"
curl "http://localhost:8983/solr/mycore/select?q=*:*&sort=price asc"

1.2 多字段排序 #

bash
# 多字段排序
curl "http://localhost:8983/solr/mycore/select?q=*:*&sort=price desc,title asc"

1.3 评分排序 #

bash
# 按相关度排序(默认)
curl "http://localhost:8983/solr/mycore/select?q=title:Solr&sort=score desc"

# 评分与其他字段组合
curl "http://localhost:8983/solr/mycore/select?q=title:Solr&sort=score desc,price asc"

二、函数排序 #

2.1 数学函数 #

bash
# 使用函数排序
curl "http://localhost:8983/solr/mycore/select?q=*:*&sort=product(price,popularity) desc"

# 使用sum函数
curl "http://localhost:8983/solr/mycore/select?q=*:*&sort=sum(views,likes) desc"

2.2 常用函数 #

函数 说明
sum(a,b) 求和
product(a,b) 乘积
div(a,b) 除法
sub(a,b) 减法
abs(x) 绝对值
log(x) 对数
sqrt(x) 平方根
pow(x,n) 幂运算

2.3 日期函数 #

bash
# 按日期距离排序
curl "http://localhost:8983/solr/mycore/select?q=*:*&sort=ms(NOW,publish_date) asc"

2.4 条件函数 #

bash
# 使用if函数
curl "http://localhost:8983/solr/mycore/select?q=*:*&sort=if(gt(popularity,100),1,0) desc"

三、排序参数 #

3.1 sort参数 #

bash
# 完整排序示例
curl "http://localhost:8983/solr/mycore/select?q=*:*&sort=score desc,popularity desc,price asc"

3.2 排序规则 #

  • 排序字段必须是indexed
  • 排序字段建议启用docValues
  • 多字段排序用逗号分隔
  • asc升序,desc降序

四、基础分页 #

4.1 分页参数 #

参数 说明 默认值
start 起始位置 0
rows 返回行数 10

4.2 分页示例 #

bash
# 第一页(0-9)
curl "http://localhost:8983/solr/mycore/select?q=*:*&start=0&rows=10"

# 第二页(10-19)
curl "http://localhost:8983/solr/mycore/select?q=*:*&start=10&rows=10"

# 第三页(20-29)
curl "http://localhost:8983/solr/mycore/select?q=*:*&start=20&rows=10"

4.3 分页计算 #

text
start = (page - 1) * rows
bash
# 第5页,每页20条
start = (5 - 1) * 20 = 80
curl "http://localhost:8983/solr/mycore/select?q=*:*&start=80&rows=20"

五、深度分页问题 #

5.1 问题说明 #

基础分页在深度分页时性能下降:

bash
# 深度分页性能差
curl "http://localhost:8983/solr/mycore/select?q=*:*&start=100000&rows=10"

5.2 原因分析 #

Solr需要:

  1. 获取前100010条结果
  2. 排序
  3. 跳过前100000条
  4. 返回后10条

5.3 解决方案 #

  • 使用Cursor分页
  • 限制最大分页深度
  • 使用过滤条件缩小范围

六、Cursor分页 #

6.1 基本用法 #

bash
# 初始请求
curl "http://localhost:8983/solr/mycore/select?q=*:*&sort=id asc&rows=10&cursorMark=*"

6.2 响应格式 #

json
{
  "response": {
    "numFound": 1000,
    "docs": [...]
  },
  "nextCursorMark": "AoE/BjQ0MTY1NQ=="
}

6.3 继续分页 #

bash
# 使用nextCursorMark继续
curl "http://localhost:8983/solr/mycore/select?q=*:*&sort=id asc&rows=10&cursorMark=AoE/BjQ0MTY1NQ=="

6.4 Cursor要求 #

  • 必须有sort参数
  • 排序字段必须包含唯一键
  • 排序字段建议启用docValues

6.5 完整示例 #

bash
# 初始请求
cursorMark="*"
while true; do
  response=$(curl -s "http://localhost:8983/solr/mycore/select?q=*:*&sort=id asc&rows=100&cursorMark=$cursorMark")
  nextCursorMark=$(echo "$response" | jq -r '.nextCursorMark')
  
  # 处理结果
  echo "$response" | jq '.response.docs'
  
  # 检查是否结束
  if [ "$cursorMark" = "$nextCursorMark" ]; then
    break
  fi
  
  cursorMark=$nextCursorMark
done

七、导出大量数据 #

7.1 使用/export #

bash
# 导出大量数据
curl "http://localhost:8983/solr/mycore/export?q=*:*&fl=id,title,price&sort=id asc"

7.2 导出要求 #

  • 字段必须启用docValues
  • 必须指定sort
  • 流式输出

7.3 配置 #

xml
<requestHandler name="/export" class="solr.SearchHandler">
  <lst name="invariants">
    <str name="rq">{!xport}</str>
    <str name="sort">id asc</str>
  </lst>
</requestHandler>

八、排序优化 #

8.1 使用DocValues #

xml
<field name="price" type="pdouble" indexed="true" stored="true" docValues="true"/>
<field name="popularity" type="pint" indexed="true" stored="true" docValues="true"/>

8.2 避免复杂排序 #

bash
# 不推荐:复杂函数排序
curl "http://localhost:8983/solr/mycore/select?q=*:*&sort=product(price,div(popularity,100)) desc"

# 推荐:预计算字段
curl "http://localhost:8983/solr/mycore/select?q=*:*&sort=score_field desc"

8.3 使用fq缩小范围 #

bash
# 先过滤再排序
curl "http://localhost:8983/solr/mycore/select?q=*:*&fq=category:tech&sort=price desc"

九、分页优化 #

9.1 限制分页深度 #

xml
<requestHandler name="/select" class="solr.SearchHandler">
  <lst name="defaults">
    <int name="rows">50</int>
  </lst>
</requestHandler>

9.2 使用Cursor代替深度分页 #

bash
# 不推荐
curl "http://localhost:8983/solr/mycore/select?q=*:*&start=10000&rows=10"

# 推荐
curl "http://localhost:8983/solr/mycore/select?q=*:*&sort=id asc&rows=10&cursorMark=*"

9.3 缓存分页结果 #

bash
# 使用fq缓存
curl "http://localhost:8983/solr/mycore/select?q=*:*&fq=category:tech&start=0&rows=10"

十、实战示例 #

10.1 商品列表排序 #

bash
# 默认排序:相关度
curl "http://localhost:8983/solr/products/select?q=手机&sort=score desc"

# 价格排序
curl "http://localhost:8983/solr/products/select?q=手机&sort=price asc"

# 销量排序
curl "http://localhost:8983/solr/products/select?q=手机&sort=sales desc"

# 综合排序
curl "http://localhost:8983/solr/products/select?q=手机&sort=score desc,sales desc,price asc"

10.2 商品列表分页 #

bash
# 基础分页
curl "http://localhost:8983/solr/products/select?q=手机&start=0&rows=20&sort=score desc"

# Cursor分页
curl "http://localhost:8983/solr/products/select?q=手机&sort=id asc&rows=20&cursorMark=*"

10.3 文章列表排序 #

bash
# 按发布日期排序
curl "http://localhost:8983/solr/articles/select?q=*:*&sort=publish_date desc"

# 按浏览量排序
curl "http://localhost:8983/solr/articles/select?q=*:*&sort=views desc"

# 按点赞数排序
curl "http://localhost:8983/solr/articles/select?q=*:*&sort=likes desc"

10.4 日志查询分页 #

bash
# Cursor分页导出日志
curl "http://localhost:8983/solr/logs/export?q=level:ERROR&fl=id,message,timestamp&sort=timestamp desc"

十一、总结 #

排序与分页要点:

功能 说明
基础排序 sort=field desc/asc
多字段排序 sort=field1 desc,field2 asc
函数排序 sort=func(field) desc
基础分页 start=0&rows=10
Cursor分页 cursorMark=*
数据导出 /export

最佳实践:

  • 排序字段启用docValues
  • 深度分页使用Cursor
  • 大量数据使用/export
  • 使用fq缩小范围
  • 限制最大分页深度

下一步,让我们学习高级特性!

最后更新:2026-03-27