如何自定义仅对 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;
}