项目中,需要对mongo中某个集合进行分组汇总,集合主要包含下面几个字段

// 日期
private Integer date;

// 账号id
private Long accountId;

// 标题
private String title;

// 状态
private Integer status;

// 状态🐴
private String statusCode;

// 数量
private Integer count;

集合主要包含下面两个索引

    {
        "v" : 2,
        "key" : {
            "date" : -1.0,
            "accountId" : 1.0,
            "status" : 1.0
        },
        "name" : "date_-1_accountId_1_status_1",
        "background" : true
    },

    {
        "v" : 2,
        "key" : {
            "date" : -1.0,
            "accountId" : 1.0,
            "title" : 1.0
        },
        "name" : "date_-1_accountId_1_title_1",
        "background" : true
    },

现在想对指定日期、指定账号下的数据不同标题下面的数量进行汇总,刚开始使用下面代码:

Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(Criteria.where("date")
.is(date).and("accountId").is(accountId)),
Aggregation.group("title", "statusCode")
.sum("count").as("totalCount"));

但是实际在测试的时候,发现速度比较慢(数据库千万级),通过查看mongo日志,发现走的是date_-1_accountId_1_status_1索引,并没有使用date_-1_accountId_1_title_1索引。

于是查询mongo官方文档Aggregation Pipeline — MongoDB Manual,怎样才能使用group中的字段索引,发现了有如下说明:

$group
The $group stage can sometimes use an index to find the first document in each group if all of the following criteria are met:

    The $group stage is preceded by a $sort stage that sorts the field to group by,

    There is an index on the grouped field which matches the sort order and

    The only accumulator used in the $group stage is $first

See Optimization to Return the First Document of Each Group for an example.

具体意思大家自己翻译,我理解的意思是,将分组group的列进行排序一下,应用到我们这个场景,就是将title字段排序一下,就可能走date_-1_accountId_1_title_1索引,聚合速度可能就更快了。

以上只是猜想,实践如下:

 Sort sort = new Sort(Sort.Direction.ASC, "title");

Aggregation aggregation = Aggregation.newAggregation(
    Aggregation.match(Criteria.where("date")
    .is(date).and("accountId").is(accountId)),
    Aggregation.sort(sort),
    Aggregation.group("title").sum("count").as("totalCount")
);

测试结果,查看mongo日志,确实走了date_-1_accountId_1_title_1索引,聚合速度相对之前也快了不少。

总结

mongo很多知识点在网上搜到的都是比较基础,很多都是告诉你Aggregation聚合基本用法,一些复杂一点的用法,还是得自己去看官方文档比较靠谱,之前遇到的几个MongoDB问题,都是通过查看官方文档解决的,官方文档也比较详细。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐