如何在Spring的Date/Time(年月日时)部分写Mongodb聚合组流水线?

How to write Mongodb aggregation group pipeline on part of Date/Time(Year, month, day, hour) in Spring?

我需要帮助在 spring 中编写 mongodb 聚合管道。

这是我要对其执行查询的数据示例(请注意,以下数据是 Match 聚合管道在 spring 中的结果它有条件使 eventDate 匹配范围并且 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 聚合管道,它应该 groupYearMonthDayHour 因为我要查找的是每小时数据。

我希望它看起来像哪些项目只有 eventDate 和 eventName 字段的结果示例:

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

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

因此,如果您注意到上面的数据是在一组小时内,除此之外,分钟和秒现在设置为 0。

我试过这个解决方案但对我不起作用:

感谢任何形式的帮助。提前致谢。

你可以在这里使用日期算法来得到日期时间,分秒毫秒部分重置为0。

您可能需要根据您的springmongo版本和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"
            }
        }
    }]
)

Spring代码:

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代码

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);