当前位置: 首页 > 面试题库 >

聚合项目组通过使用Spring Data提取日,月和年

蒲昊苍
2023-03-14
问题内容

直接来说,我该怎么做:

group._id = { 
    year: { $year : [{ $subtract: [ "$timestamp", 25200000 ]}] }, 
    month: { $month : [{ $subtract: [ "$timestamp", 25200000 ]}] }, 
    day: { $dayOfMonth : [{ $subtract: [ "$timestamp", 25200000 ]}] }
};

带有弹簧数据

我已经尝试过这种方法和其他一些形式,但没有成功

Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(c),
                Aggregation.project("programa", "custo", "duracao", "dataHora")
                    .andExpression("dataHora").minus(25200000).extractDayOfMonth().as("dia")
                    .andExpression("dataHora").minus(25200000).extractMonth().as("mes")
                    .andExpression("dataHora").minus(25200000).extractYear().as("ano"),
                Aggregation.group("programa", "ano", "mes", "dia")
                    .count().as("count")
                    .sum("custo").as("valorTotal")
                    .sum("duracao").as("duracaoTotal")
                    .first("dataHora").as("dataHora"),
                Aggregation.sort(Direction.ASC, "dataHora")
        );

我需要在mongodb中按日,月和年分组,否则我将需要在代码中转换所有这些分组的数据。

提前致谢


问题答案:

您在单一$project阶段可以进行字段计算时遇到了Spring
mongo的局限性,并且实际上您可能已经单独编写了,$project因为您发现目前也不能直接在项目中自定义命名字段。$group
_id

因此,最好将所有内容都保留在中$group,并使用其他方法将调整后的日期四舍五入为当地时间。

因此,更好的写方法$group是:

{ "$group": {
  "_id": {
    "programa": "$programa",
    "dataHora": {
      "$add": [
        { "$subtract": [
          { "$subtract": [{ "$subtract": ["$dataHora", new Date(0)] }, 25200000 ] },
          { "$mod": [
            { "$subtract": [{ "$subtract": ["$dataHora", new Date(0)] }, 25200000 ] },
            1000 * 60 * 60 * 24
          ]}
        ]},
        new Date(0)
      ]
    }
  },
  "count": { "$sum": 1 },
  "valorTotal": { "$sum": "$custo" },
  "duracaoTotal": { "$sum": "$duracao" },
  "dataHora": { "$first": "$dataHora" }
}}

当然,要将这种结构与spring-mongo结合使用,您需要一个聚合阶段操作的自定义实现,该实现可以采用定义DBObject

public class CustomGroupOperation implements AggregationOperation {
    private DBObject operation;

    public CustomGroupOperation (DBObject operation) {
        this.operation = operation;
    }

    @Override
    public DBObject toDBObject(AggregationOperationContext context) {
        return context.getMappedObject(operation);
    }
}

然后在如下上下文中使用它:

    Aggregation aggregation = Aggregation.newAggregation(
            Aggregation.match(c),
            new CustomGroupOperation(
                new BasicDBObject("$group",
                    new BasicDBObject("_id",
                        new BasicDBObject("programa","$programa")
                            .append("dataHora",
                                new BasicDBObject("$add",Arrays.asList(
                                    new BasicDBObject("$subtract",Arrays.asList(
                                        new BasicDBObject("$subtract",Arrays.asList(
                                            new BasicDBObject("$subtract",Arrays.asList(
                                                "$dataHora", new Date(0)
                                            )),
                                            25200000
                                        )),
                                        new BasicDBObject("$mod",Arrays.asList(
                                            new BasicDBObject("$subtract",Arrays.asList(
                                                new BasicDBObject("$subtract",Arrays.asList(
                                                    "$dataHora", new Date(0)
                                                )),
                                                25200000
                                            )),
                                            1000 * 60 * 60 * 24
                                        ))
                                    )),
                                    new Date(0)
                                ))
                            )
                    )
                    .append("count",new BasicDBObject("$sum",1))
                    .append("valorTotal",new BasicDBObject("$sum","$custo"))
                    .append("duracaoTotal",new BasicDBObject("$sum","$duracao"))
                    .append("dataHora",new BasicDBObject("$first","$dataHora"))
                )
            ),
            Aggregation.sort(Direction.ASC,"_id.dataHora")
    );

由于定制类是从内置辅助方法使用的同一基本类中抽象出来的,因此可以如图所示将其与它们一起使用。

日期数学的基本过程在这里是如何工作的,当您将$subtract另一个BSON
Date对象与另一个对象进行比较时,结果是相差的毫秒数,在这种情况下,是从纪元日期(Date(0))提取出来的毫秒数。这使您可以进行数学运算,以$mod一天中的毫秒数乘以模()来舍入到当前日期值。

就像您最初尝试过的那样,当您然后$add将该BSON
Date对象的毫秒值返回时,返回的值再次是BSON Date。因此,添加到表示纪元的对象将返回一个新的Date对象,但四舍五入到当前日期。

这通常比通过日期聚合运算符提取零件有用得多,并且计算出来的代码要短一些,尤其是在调整此处从UTC的时间时。

尽管$group这里的结构比Spring
mongo的帮助函数要避免的简洁得多,但最终它比运行一个单独的$project阶段来转换您仅在该$group阶段真正想要的字段值要有效得多无论如何。



 类似资料:
  • 目前,我有个问题。我可以在mongodb中使用聚合函数查询相应的数据,但是在使用springdatamongodb后,我发现lookup不能使用变量将string转换为objectid,那么该如何编写这个聚合函数呢 如何在spring data mogodb中将其写成mongodb表达式

  • 我的模式实现受到了mongo官方网站上这篇教程的影响 这基本上是为时间序列数据设计的模式,我将每个设备每小时的数据存储在单个文档中的数组中。我创建字段组合发送数据和时间的设备id。例如,如果id为的设备在发送数据,则我的 字段将变为

  • 问题内容: 我有一个数据集,其中包含对频率为2分钟的几周的观察。我想将时间间隔从2分钟增加到5分钟。问题在于,观察的频率并不总是相同的。我的意思是,从理论上讲,每10分钟应进行5次观察,但通常情况并非如此。请让我知道如何根据平均功能以及观察的时间和日期汇总观察。换句话说,基于每5分钟的汇总,而对于每5分钟的时间间隔,观察次数却不同。此外,我有时间戳格式的日期和时间。 示例数据: 预期成绩: 问题答

  • 我正在遵循这个关于通过java API创建YarnApp的示例。 https://github.com/hortonworks/simple-yarn-app 工作正常,但日志只存在于执行中,之后日志就消失了。 我怎么能通过代码捕捉到这个?或者启用一个选项?

  • 我在这里读了很多问题和答案,但我找不到一个能消除我疑虑的aswer。 我有一个用管理的大型Java项目(我们称之为MainProj),它有许多依赖项,其中一些是我和我的团队完成的其他独立项目。 我所做的是为每个相关项目创建一个maven项目,将每个项目安装到我的存储库中,并使用标准的导入导入到MainProj中。 我已经读过superPom(或parent pom)的概念,但我不知道它是如何工作的

  • 本文向大家介绍IDEA创建parent项目(聚合项目),包括了IDEA创建parent项目(聚合项目)的使用技巧和注意事项,需要的朋友参考一下 关于聚合项目和父项目的概念有兴趣的可以去看《MAVEN实战这本书籍》,本篇描述使用IDEA工具创建继承和聚合项目的过程! 创建空白工程:作为存放项目的root目录 步骤一: 步骤2: 步骤3: maven继承:创建父-子项目 项目的结构示意图如下: 1.创