如何在Spring的部分日期/时间(年,月,日,小时)上编写Mongodb聚合组管道?

时间:2017-02-02 20:05:55

标签: spring mongodb aggregation-framework spring-mongo

我需要帮助在春天编写mongodb聚合管道。

以下是我想要执行查询的数据示例(请注意,以下数据是春天匹配聚合管道的结果,其中有条件让eventDate与之匹配range和eventName等于' A'):

    {
        "_id": ObjectId("1234567890"),
        "eventDate": ISODate("2017-01-29T03:56:04.297Z"),
        "eventName": "A"
    }

    {
        "_id": ObjectId("1234567890"),
        "eventDate": ISODate("2017-01-29T03:57:04.887Z"),
        "eventName": "A"
    }

    {
        "_id": ObjectId("1234567890"),
        "eventDate": ISODate("2017-01-29T04:05:00.497Z"),
        "eventName": "A"
    }

现在我想在eventDate字段上编写 Group 聚合管道,在 分组 >,小时,因为我要查找的是每小时数据。

结果示例我希望它看起来像只调度eventDate和eventName字段:

    {
        "eventDate": ISODate("2017-01-29T03:00:00.000Z"),
        "eventName": "A"
    }

    {
        "eventDate": ISODate("2017-01-29T04:00:00.000Z"),
        "eventName": "A"
    }

因此,如果您注意到上面的数据是在一小时内的一小时内,那么分钟和秒数现在都设置为0.

我试过这个解决方案,但对我不起作用: MongoTemplate aggregate - group by date

任何形式的帮助表示赞赏。提前谢谢。

1 个答案:

答案 0 :(得分:0)

您可以在此处使用日期算法将日期时间,分钟,秒和毫秒部分重置为0。

您可能需要根据spring mongo版本和java版本进行一些调整。

版本:Mongo 3.2,Spring Mongo 1.9.5版本和Java 8

Mongo Shell查询:

db.collection.aggregate(
    [{
        $group: {
            _id: {
                $subtract: ["$eventDate", {
                    $add: [{
                        $multiply: [{
                            $minute: "$eventDate"
                        }, 60000]
                    }, {
                        $multiply: [{
                            $second: "$eventDate"
                        }, 1000]
                    }, {
                        $millisecond: "$eventDate"
                    }]
                }]
            },
            eventName: {
                $addToSet: "$eventName"
            }
        }
    }]
)

春季代码:

AggregationOperation group = context -> context.getMappedObject(new BasicDBObject(
    "$group", new BasicDBObject(
    "_id",
    new BasicDBObject(
        "$subtract",
        new Object[]{
            "$eventDate",
            new BasicDBObject("$add",
                new Object[]{
                    new BasicDBObject("$multiply", 
                        new Object[]{new BasicDBObject("$minute", "$eventDate"), 60000}),
                    new BasicDBObject("$multiply", 
                        new Object[]{new BasicDBObject("$second", "$eventDate"), 1000}),
                    new BasicDBObject("$millisecond", "$eventDate")
                }
            )
        }
    )
).append("eventName", new BasicDBObject("$addToSet", "$eventName"))));

更新:使用$ project

db.collection.aggregate(
    [{
        $project: {
            eventDate: {
                $subtract: ["$eventDate", {
                    $add: [{
                        $multiply: [{
                            $minute: "$eventDate"
                        }, 60000]
                    }, {
                        $multiply: [{
                            $second: "$eventDate"
                        }, 1000]
                    }, {
                        $millisecond: "$eventDate"
                    }]
                }]
            },
            eventName: 1
        }
    }, {
        $group: {
            _id: "$eventDate",
            eventName: {
                $addToSet: "$eventName"
            }
        }
    }]
)

Spring Code

AggregationOperation project = context -> context.getMappedObject(new BasicDBObject(
"$project", new BasicDBObject(
"eventDate",
new BasicDBObject(
    "$subtract",
    new Object[]{
        "$eventDate",
        new BasicDBObject("$add",
            new Object[]{
                new BasicDBObject("$multiply", 
                    new Object[]{new BasicDBObject("$minute", "$eventDate"), 60000}),
                new BasicDBObject("$multiply", 
                    new Object[]{new BasicDBObject("$second", "$eventDate"), 1000}),
                new BasicDBObject("$millisecond", "$eventDate")
            }
        )
    }
)
).append("eventName", 1)));

AggregationOperation group = Aggregation.group("eventDate").addToSet("eventName").as("eventName");

Aggregation agg = Aggregation.newAggregation(project, group);