排序与分页 #
一、排序 #
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需要:
- 获取前100010条结果
- 排序
- 跳过前100000条
- 返回后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