【问题标题】:Spring Data MongoDB Aggregation framework, exception accessing computed value in groupSpring Data MongoDB聚合框架,异常访问组中的计算值
【发布时间】:2014-05-11 02:32:52
【问题描述】:

我有一个行程集合,每个行程都有一个 startDateTime 和一个 completionDateTime 属性。

我正在尝试使用聚合框架来查找用户旅行的平均持续时间。

我的聚合看起来很简单,但它会引发异常。

下面有 3 个步骤,第一个只是匹配到特定 userId 的行程。 在管道的第二步中,我将我感兴趣的数据与新计算的每次旅行的持续时间一起投影。

我预计投影的持续时间在组步骤中可用,但我得到下面的 IllegalArgumentException。 Duration 不是我的 Trip 类的属性,但从我在文档中看到的示例来看,我认为不需要。 Duration 是我的分析类的一个属性。

TypedAggregation<Trip> aggregation = newAggregation(Trip.class, 
    match(Criteria.where("userId").is(aUserId)),

    project("completionDateTime", "startDateTime", "userId")
    .and("completionDateTime").minus("startDateTime").as("duration"),

    group("userId").avg("duration").as("averageDuration")
);
AggregationResults<Analytics> result = mongoTemplate.aggregate(aggregation, Analytics.class);

我相信持续时间的计算是正确的,就好像我省略了组步骤一样,我返回了一组文档并且它们都设置了持续时间。

java.lang.IllegalArgumentException: Invalid reference 'duration'!
    at org.springframework.data.mongodb.core.aggregation.ExposedFieldsAggregationOperationContext.getReference(ExposedFieldsAggregationOperationContext.java:78)
    at org.springframework.data.mongodb.core.aggregation.GroupOperation$Operation.getValue(GroupOperation.java:367)
    at org.springframework.data.mongodb.core.aggregation.GroupOperation$Operation.toDBObject(GroupOperation.java:363)
    at org.springframework.data.mongodb.core.aggregation.GroupOperation.toDBObject(GroupOperation.java:308)
    at org.springframework.data.mongodb.core.aggregation.Aggregation.toDbObject(Aggregation.java:247)

我正在使用 1.3.4.RELEASE

有什么建议吗?

【问题讨论】:

  • 您能否准确地更新您的问题,说明您是如何针对 1.4 进行尝试的,以及您是否遇到了完全相同的异常(如果没有,您能否包括您确实得到的异常?)
  • @AsyaKamsky 我使用了完全相同的代码并得到了与 1.4.1.RELEASE 完全相同的异常

标签: spring mongodb spring-data aggregation-framework spring-data-mongodb


【解决方案1】:

升级到 1.4.1 后,我能够使用以下方法获得所需的结果:

.andExpression("completionDateTime - startDateTime").as("duration")

【讨论】:

  • 您可以编辑您的问题或将其添加为评论,除非它是一个答案,否则它不应该出现在这里......
  • 这是答案,需要24小时才能接受我自己的答案。
  • 这没有提供问题的答案。要批评或要求作者澄清,请在其帖子下方发表评论。
  • @ArtemBilan 您是否需要澄清?我想知道如何计算投影中的值并在组中访问它。这是针对 Spring 数据框架中似乎存在错误的解决方法。
  • 知道了,抱歉。投票给你
【解决方案2】:

您似乎遇到了https://jira.spring.io/browse/DATAMONGO-838,所以在它修复之前,您可能需要找出一种不同的方法来做您需要的事情。

在使用 js 的 mongo shell 中,您不需要 $project 字段,您可以直接将计算表达式替换为组,如下所示:

db.collection.aggregate( {$match:{ your-match } },
     { $group : { 
         _id : "$userId",
         avgDuration : { $avg : {$subtract:["$completionDateTime","startDateTime"]}},
     } } );

在 Spring 中可能可以返回表达式以执行此操作。如果没有,您的另一个选择是通过 Java 驱动程序将聚合直接传递给 MongoDB,绕过 Spring,直到修复错误。

【讨论】:

  • 很好的建议。实际上,该错误修复已经在发布版本中可用。您介意相应地更新您的答案吗?我真的不想添加另一个答案,基本上是重复你所说的。
  • 恐怕我过早地接受了这个答案。我刚刚更新到 1.4.1.RELEASE 版本,仍然得到同样的错误。修复程序是否在其他版本中?或者也许这是一个不同的问题?
  • 当然,我会根据更新的错误信息进行编辑 - 但我确实看到它在 1.4GA 中被标记为已修复,因此要么没有修复,要么在所有情况下都没有修复,或者不是完全相同的错误,而是以相同方式表现出来的不同错误。
  • @DannyLane 您是否尝试过不使用项目并将计算表达式直接放入 $group 阶段的解决方法?
  • @AsyaKamsky 我没有尝试将计算表达式直接放在小组赛阶段,因为我想多次使用投影值(最小值、最大值、平均值)。我真的很想在项目步骤中设置它,我上面使用 .andExpression 的答案适用于此。
猜你喜欢
  • 1970-01-01
  • 2018-09-25
  • 1970-01-01
  • 2015-11-19
  • 1970-01-01
  • 2013-12-25
  • 1970-01-01
  • 2021-06-15
  • 2019-07-24
相关资源
最近更新 更多