PAYATHON 2026

如何使用 MongoDB Java driver 按聚合计算的平均值排序?

数据阿明

在聚合管道的 Aggregates.group(...) 后添加 Aggregates.sort(...),即可按 Average Vendor Transaction Sent 排序。无需先保存到新集合,也不必在 Java 中另行排序。

为什么计算结果也能按字段名排序?

Accumulators.avg("Average Vendor Transaction Sent", "$amount sent") 会把平均值写入分组结果的 Average Vendor Transaction Sent 字段。

原始文档虽然没有这个字段,但 $group 执行后的文档已包含它,例如:

{
  "_id": "HECTOR'S YOUR I",
  "Average Vendor Transaction Sent": 27.72
}

后续管道阶段可以使用前面阶段生成的字段,因此可以通过 Sorts 引用它。

在 $group 后添加排序阶段

下面按平均交易金额从大到小排序:

import com.mongodb.client.AggregateIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Accumulators;
import com.mongodb.client.model.Aggregates;
import com.mongodb.client.model.Sorts;
import org.bson.Document;

import java.util.Arrays;

private static AggregateIterable<Document> averageVendorTotalSent(
        MongoCollection<Document> collection) {
    return collection.aggregate(Arrays.asList(
        Aggregates.group(
            "$transaction vendor",
            Accumulators.avg(
                "Average Vendor Transaction Sent",
                "$amount sent"
            )
        ),
        Aggregates.sort(
            Sorts.descending("Average Vendor Transaction Sent")
        )
    ));
}

如果需要从小到大排序,将排序阶段改成:

Aggregates.sort(
    Sorts.ascending("Average Vendor Transaction Sent")
)

其中,Sorts.descending(...) 或 Sorts.ascending(...) 构造排序条件,Aggregates.sort(...) 将条件包装成聚合管道中的 $sort 阶段。

字段名和管道顺序要注意什么?

排序时传入字段名,不要添加 $ 前缀:

Sorts.descending("Average Vendor Transaction Sent")

原代码中的 "$amount sent" 是聚合表达式中的字段引用;Sorts.descending(...) 的参数则是排序字段名,两处写法不同。字段名中的空格可以保留,但名称需要与 Accumulators.avg(...) 定义的输出字段完全一致。

排序阶段必须放在 $group 后面,因为平均值到这时才生成。如果在 $group 前按 amount sent 排序,排列的是原始交易记录,无法让最终结果按各商家的平均金额排列;$group 本身也不保证输出顺序。

这个需求不需要额外的 $project 阶段。如果平均值相同,还希望按商家名称排列,可以增加 _id 作为第二排序条件:

Aggregates.sort(Sorts.orderBy(
    Sorts.descending("Average Vendor Transaction Sent"),
    Sorts.ascending("_id")
))

这里的 _id 是 $group 输出的分组键,对应原始文档中的 transaction vendor。

备注:内容仅供参考。