排序
# EE内置排序
针对字段的排序,EE提供了一些内置开箱即用的API,用于支持升序排序和降序排序:
// 降序排列
wrapper.orderByDesc(排序字段,支持多字段)
// 升序排列
wrapper.orderByAsc(排序字段,支持多字段)
// 根据得分排序(此功能0.9.7+版本支持;不指定SortOrder时默认降序,得分高的在前,支持升序/降序)
wrapper.sortByScore(boolean condition,SortOrder sortOrder)
// 排序入参由前端传入, 字符串格式,有点类似之前MySQL那种
wrapper.orderBy(boolean condition, OrderByParam orderByParam);
// 排序入参由前端传入,多字段情形
wrapper.orderBy(boolean condition, List<OrderByParam> orderByParams);
// 根据距离由近及远排序
wrapper.orderByDistanceAsc(boolean condition, R column, Geopoint...geoPoints);
// 根据距离由远及近排序
wrapper.orderByDistanceDesc(boolean condition, R column, Geopoint...geoPoints);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
使用示例:
@Test
public void testSort(){
// 测试排序 为了测试排序,我们在Document对象中新增了创建时间字段,更新了索引,并新增了两条数据
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
wrapper.likeRight(Document::getContent,"推");
wrapper.select(Document::getTitle,Document::getGmtCreate);
List<Document> before = documentMapper.selectList(wrapper);
System.out.println("before:"+before);
wrapper.orderByDesc(Document::getGmtCreate);
List<Document> desc = documentMapper.selectList(wrapper);
System.out.println("desc:"+desc);
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
@Test
public void testSortByScore(){
// 测试根据得分升序排列(分数低的排前面)
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
wrapper.match(Document::getContent,"技术");
wrapper.sortByScore(SortOrder.ASC);
List<Document> documents = documentMapper.selectList(wrapper);
System.out.println(documents);
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
@Test
public void testOrderByParams(){
// 此处模拟参数由前端通过xxQuery类传入,排序根据标题降序,根据内容升序
String jsonParam = "[{\"order\":\"title\",\"sort\":\"DESC\"},{\"order\":\"creator\",\"sort\":\"ASC\"}]";
List<OrderByParam> orderByParams = JSON.parseArray(jsonParam, OrderByParam.class);
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
wrapper.match(Document::getContent,"技术")
.orderBy(orderByParams);
List<Document> documents = documentMapper.selectList(wrapper);
System.out.println(documents);
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
@Test
public void testOrderByDistanceAsc() {
// 测试给定中心点, 查询出中心点168.8km范围内的数据,并按照距中心点距离由近及远排序
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
GeoPoint centerPoint = new GeoPoint(41.0, 116.0);
wrapper.match(Document::getCreator, "老汉")
.geoDistance(Document::getLocation, 168.8, centerPoint)
.orderByDistanceAsc(Document::getLocation, centerPoint);
List<Document> documents = documentMapper.selectList(wrapper);
System.out.println(documents);
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
@Test
public void testOrderByDistanceAsc() {
// 测试给定中心点, 查询出中心点168.8km范围内的数据,并按照距中心点距离由远及近排序
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
GeoPoint centerPoint = new GeoPoint(41.0, 116.0);
wrapper.match(Document::getCreator, "老汉")
.geoDistance(Document::getLocation, 168.8, centerPoint)
.orderByDistanceDesc(Document::getLocation, centerPoint);
List<Document> documents = documentMapper.selectList(wrapper);
System.out.println(documents);
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
效果:
# 自定义排序
背景
ES的排序器非常丰富多变,也足够灵活,我们很难用一套固定的方案将所有排序都简化。因此我们针对上面这些高频的排序提供了开箱即用的支持,对于其它低频使用的排序,将排序建造者通过自定义的方式直接委托给用户使用,无疑是目前较好的解决方案,如此便可以在不使用原生查询和混合查询的前提下,还能100%支持ES提供的所有查询功能。而且随着不断迭代和吸纳用户反馈,在不久的将来,我们也会持续提供更多开箱即用的API支持,敬请期待。
// API
wrapper.sort(boolean condition, SortBuilder<?> sortBuilder)
1
2
2
使用示例:
@Test
public void testSort(){
// 测试复杂排序,SortBuilder的子类非常多,这里仅演示一种, 比如有用户提出需要随机获取数据
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
wrapper.match(Document::getContent,"技术");
Script script = new Script("Math.random()");
ScriptSortBuilder scriptSortBuilder = new ScriptSortBuilder(script, ScriptSortBuilder.ScriptSortType.NUMBER);
wrapper.sort(scriptSortBuilder);
List<Document> documents = documentMapper.selectList(wrapper);
System.out.println(documents);
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
SortBuilder类的子类非常多,也非常灵活,所以能支撑和覆盖的排序场景也足够多,其它各种类型的查询,如果您在使用过程中有碰到,可以参考上面的例子去写
帮助我们改善此文档 (opens new window)
上次更新: 2024/05/18