【问题标题】:how to use $month using aggregation in spring data mongo db如何在 Spring Data MongoDB 中使用 $month 聚合
【发布时间】:2016-02-10 10:30:11
【问题描述】:

我正在使用 mongodb。我必须在我的 spring 数据 mongo db 中对 $date 使用聚合查询。这是我的用户收藏。

{
    "_id" : NumberLong(70289),
    "_class" : "com.samepinch.domain.user.User",
    "age" : 25,
    "roles" : [
        "ROLE_MODERATOR",
        "ROLE_USER"
    ],
    "firstName" : "Abhi",
    "lastName" : "Saini",
    "email" : "abhisheksn138@gmail.com",
    "createdDate" : ISODate("2015-12-04T12:29:57.604Z"),
    "updatedDate" : ISODate("2016-02-10T06:23:13.314Z")
}

这是我的 mongodb 查询

 db.users.aggregate([{ $project : { month_joined : { $month : "$createdDate" } } } ,{ $group : { _id : {month_joined:"$month_joined"} , number : { $sum : 1 } } },{ $sort : { "_id.month_joined" : 1 } }])

查询给了我想要的结果:

{ "_id" : { "month_joined" : 1 }, "number" : 19 }
{ "_id" : { "month_joined" : 2 }, "number" : 7 }
{ "_id" : { "month_joined" : 9 }, "number" : 16 }
{ "_id" : { "month_joined" : 10 }, "number" : 12 }
{ "_id" : { "month_joined" : 11 }, "number" : 11 }
{ "_id" : { "month_joined" : 12 }, "number" : 13 }

现在我必须使用 mongotemplate 在 spring data mongodb 中编写这个查询。我是使用聚合的新手。他们是否有任何简单的使用方法。请帮忙

谢谢。

【问题讨论】:

    标签: java mongodb spring-mvc spring-data-mongodb


    【解决方案1】:

    您可以尝试先在投影操作中使用 SpEL andExpression 来投影字段,然后在分组操作中按新字段分组:

    Aggregation agg = newAggregation(
        project("id").andExpression("month(createdDate)").as("month_joined"),
        group("month_joined").count().as("number"),
        project("number").and("month_joined").previousOperation(),
        sort(ASC, "number")
    );
    
    AggregationResults<JoinCount> results = mongoTemplate.aggregate(agg, 
                                                         "collectionName", JoinCount.class);
    List<JoinCount> joinCount = results.getMappedResults();
    

    在上面,通过 newAggregation 静态工厂方法创建了一个新聚合,您将聚合操作列表传递给该方法。这些聚合操作定义了聚合的聚合管道。

    在第一步中,您使用 SpEL andExpression 和项目操作从输入集合中投射字段。

    在第二步中,您使用组操作为每个 "month_joined"-value 定义一个组,您通过 count() 聚合运算符聚合其出现次数,并将结果收集到一个名为 "number" 的新字段中。

    作为第三步,选择字段"number" 并为从先前组操作(因此调用previousOperation())生成的_id 字段创建一个别名,名称为"month_joined"

    作为第四步,通过排序操作按出现次数升序对分组的month_joined 文档的结果列表进行排序。

    最后在 MongoTemplate 上调用 aggregate() 方法,以便让 MongoDB 以创建的 Aggregation 作为参数执行实际的聚合操作。


    要过滤当前年份进入管道的文档,您需要投影一个包含日期的年份部分的新字段,并在项目步骤之后发出匹配运算符,例如

    Aggregation agg = newAggregation(
        project("id")
            .andExpression("month(createdDate)").as("month_joined")
            .andExpression("year(createdDate)").as("year"),
        match(Criteria.where("year").is(2016)),
        group("month_joined").count().as("number"),
        project("number").and("month_joined").previousOperation(),
        sort(ASC, "number")
    );
    
    AggregationResults<JoinCount> results = mongoTemplate.aggregate(agg, 
                                                         "collectionName", JoinCount.class);
    List<JoinCount> joinCount = results.getMappedResults();
    

    【讨论】:

    • 当我使用 project() 时。和表达式()。它要求我提供 andExpression(字符串表达式,对象参数)。根据你的回答不知道怎么用?
    • 您是否尝试过.andExpression("month(createdDate)") 而不是之前显示的.andExpression("month(date)")
    • 实际上 .andExpression() 要求两个参数,即 andExpression(String expression,Object Params)。我很困惑传递什么。
    • 感谢#chridam 它为我所做的工作。 :) 但是,如果我只想计算当年每个月的用户数,我该怎么办?
    • Waaooow 它的工作。非常感谢#chridam 抽出时间并更新答案。 :)
    【解决方案2】:

    从 2.1 开始,您可以使用 DateOperators.Month

    Aggregation agg = newAggregation(
        project("id").and(DateOperators.Month.month("createdDate")).as("month_joined"),
        group("month_joined").count().as("number"),
        project("number").and("month_joined").previousOperation(),
        sort(ASC, "number")
    );
    

    【讨论】:

    • 在createDate之前需要$,否则会出现异常:can't convert from BSON type string to Date.
    猜你喜欢
    • 1970-01-01
    • 2017-10-02
    • 2021-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-13
    • 1970-01-01
    • 2014-01-30
    相关资源
    最近更新 更多