如何自定义仅对 Spring MongoDB 中的特定结果进行排序?
How to custom sort only specific results in Spring MongoDB?
是否可以仅对符合 Spring Mongo 中的条件的结果进行排序?
假设我有这个数据:
Color
Fruit
Amount
Orange
Orange
23
Red
Apple
4
Red
Strawberry
66
Yellow
Banana
2
我想对列表进行排序,将红色的水果显示在顶部,其余的水果将按数量排序。所以结果 table 应该是。
Color
Fruit
Amount
Red
Apple
4
Red
Strawberry
66
Yellow
Banana
2
Orange
Orange
23
到目前为止,这是我尝试使用聚合的方法。
val match1: MatchOperation = Aggregation.match(Criteria("Color").`is`("Red"))
val match2: MatchOperation = Aggregation.match(Criteria("Color").`is`("Red").not())
val sortByAmount= sort(Sort.Direction.ASC, "Amount")
val aggregation = Aggregation.newAggregation(match1, sortByAmount, match2, sortByAmount)
val output: AggregationResults<Fruits> = mongoTemplate.aggregate(aggregation, "fruits", Fruits::class.java)
但我只是得到这个结果
Color
Fruit
Amount
Red
Apple
4
Red
Strawberry
66
一种方法是使用 $facet
;有两个方面,一个代表“红色”,另一个代表“非红色”。
Aggregation agg = newAggregation(
facet(
match(where("color").is("red")),
sort(ASC, "amt"))
.as("reds")
.and(
match(where("color").ne("red")),
sort(ASC, "amt")
).as("others"),
project()
.and(arrayOf("reds").concat("others"))
.as("result"),
unwind("result"),
replaceRoot("result")
);
AggregationResults<Document> results = mongoTemplate.aggregate(agg, "fruits", Document.class);
results.forEach(doc -> System.out.println(doc.toJson());
为简洁起见,我按如下方式使用输入文档:{ color: 'red', amt: 12 }, { color: 'blue', amt: 2 }, { color: 'green', amt: 4 }, { color: 'red', amt: 3 }, { color: 'yellow', amt: 5 }
另一种方法 是使用 $function
运算符。这需要 Spring Data MongoDB v3.2 和 MongoDB v4.4。我没有机会实际 运行 代码(我认为它应该有效)。
将使用以下四个阶段构建管道:
GroupOperation groupOperation = Aggregation.group().push("$$ROOT").as("docs");
AddFieldsOperation addFieldsOperation = Aggregation.addFields()
.addFieldWithValue("docs",
ScriptOperators.Function.function(JAVASCRIPT_FUNCTION).args("docs").lang("js"))
.build();
UnwindOperation unwindOperation = Aggregation.unwind("docs");
ReplaceRootOperation replaceRootOperation = Aggregation.replaceRoot("docs");
字符串 JAVASCRIPT_FUNCTION(在 AddFieldsOperation
中使用)具有以下 JavaScript 函数,该函数实际对 fruits 文档的数组进行排序.
function (a, b) {
if (a.color == 'red' && b.color == 'red') {
return a.amt - b.amt;
}
if (a.color == 'red' || b.color == 'red') {
if (a.color == 'red') return 0;
return 1;
}
return a.amt - b.amt;
}
是否可以仅对符合 Spring Mongo 中的条件的结果进行排序? 假设我有这个数据:
Color | Fruit | Amount |
---|---|---|
Orange | Orange | 23 |
Red | Apple | 4 |
Red | Strawberry | 66 |
Yellow | Banana | 2 |
我想对列表进行排序,将红色的水果显示在顶部,其余的水果将按数量排序。所以结果 table 应该是。
Color | Fruit | Amount |
---|---|---|
Red | Apple | 4 |
Red | Strawberry | 66 |
Yellow | Banana | 2 |
Orange | Orange | 23 |
到目前为止,这是我尝试使用聚合的方法。
val match1: MatchOperation = Aggregation.match(Criteria("Color").`is`("Red"))
val match2: MatchOperation = Aggregation.match(Criteria("Color").`is`("Red").not())
val sortByAmount= sort(Sort.Direction.ASC, "Amount")
val aggregation = Aggregation.newAggregation(match1, sortByAmount, match2, sortByAmount)
val output: AggregationResults<Fruits> = mongoTemplate.aggregate(aggregation, "fruits", Fruits::class.java)
但我只是得到这个结果
Color | Fruit | Amount |
---|---|---|
Red | Apple | 4 |
Red | Strawberry | 66 |
一种方法是使用 $facet
;有两个方面,一个代表“红色”,另一个代表“非红色”。
Aggregation agg = newAggregation(
facet(
match(where("color").is("red")),
sort(ASC, "amt"))
.as("reds")
.and(
match(where("color").ne("red")),
sort(ASC, "amt")
).as("others"),
project()
.and(arrayOf("reds").concat("others"))
.as("result"),
unwind("result"),
replaceRoot("result")
);
AggregationResults<Document> results = mongoTemplate.aggregate(agg, "fruits", Document.class);
results.forEach(doc -> System.out.println(doc.toJson());
为简洁起见,我按如下方式使用输入文档:{ color: 'red', amt: 12 }, { color: 'blue', amt: 2 }, { color: 'green', amt: 4 }, { color: 'red', amt: 3 }, { color: 'yellow', amt: 5 }
另一种方法 是使用 $function
运算符。这需要 Spring Data MongoDB v3.2 和 MongoDB v4.4。我没有机会实际 运行 代码(我认为它应该有效)。
将使用以下四个阶段构建管道:
GroupOperation groupOperation = Aggregation.group().push("$$ROOT").as("docs");
AddFieldsOperation addFieldsOperation = Aggregation.addFields()
.addFieldWithValue("docs",
ScriptOperators.Function.function(JAVASCRIPT_FUNCTION).args("docs").lang("js"))
.build();
UnwindOperation unwindOperation = Aggregation.unwind("docs");
ReplaceRootOperation replaceRootOperation = Aggregation.replaceRoot("docs");
字符串 JAVASCRIPT_FUNCTION(在 AddFieldsOperation
中使用)具有以下 JavaScript 函数,该函数实际对 fruits 文档的数组进行排序.
function (a, b) {
if (a.color == 'red' && b.color == 'red') {
return a.amt - b.amt;
}
if (a.color == 'red' || b.color == 'red') {
if (a.color == 'red') return 0;
return 1;
}
return a.amt - b.amt;
}