2

I have a collection of trips and every trip has a startDateTime and a completionDateTime property.

I'm trying to use the aggregation framework to find the average duration of a users' trips.

My aggregation seems simple enough and but it throws an exception.

There are 3 steps below, the first just matches the trips to a specific userId. In the second step of the pipeline I project the data I'm interested in along with the newly calculated duration of each trip.

I expected the duration from the projection to be available in the group step but I get the IllegalArgumentException below. Duration Is not a property on my Trip class but from the examples I've seen in the docs I don't think it needs to be. Duration is a property on my analytics class.

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

I believe the duration is getting calculated correctly as if I leave out the group step I get back a collection of documents and they all have the duration set.

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)

I'm using 1.3.4.RELEASE

Any Suggestions?

2
  • could you update your question with exactly how you ran the attempt against 1.4 and whether you got the exact same exception (if not could you include the one you did get?) Commented Apr 1, 2014 at 13:08
  • @AsyaKamsky I used the exact same code and got the exact same exception with 1.4.1.RELEASE Commented Apr 2, 2014 at 7:32

2 Answers 2

3

After upgrading to 1.4.1 I was able to get the desired result using:

.andExpression("completionDateTime - startDateTime").as("duration")
Sign up to request clarification or add additional context in comments.

6 Comments

you can edit your question or add this as a comment, it shouldn't go down here unless it's an answer...
This is the answer, it takes 24 hours to be able to accept my own answer.
This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post.
@ArtemBilan Are you looking for clarification? I wanted to know how to compute a value in a projection and access it in a group. This is a work around for what appears to be a bug in the spring data framework.
Got it, sorry. Voting you
|
1

It looks like you are running into https://jira.spring.io/browse/DATAMONGO-838 so until it's fixed you may need to figure out a different way to do what you need.

In mongo shell using js you don't need to have a $project field, you can just substitute in the computed expression into the group directly like so:

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

It might be possible to return the expression to do it this way in Spring. If not, your other option is to pass the aggregation directly to MongoDB through the Java driver, bypassing Spring until the bug is fixed.

7 Comments

Great advice. Actually the bug fix is already available in a released version. Would you mind updating your answer accordingly? I don't really want to add another answer basically repeating what you said.
I prematurely accepted this answer I'm afraid. I just updated to the 1.4.1.RELEASE version and still get the same error. Is the fix in a different version? Or maybe it's a different issue?
sure, I'll edit based on updated bug info - but I do see that it was marked as being fixed in 1.4GA so either it wasn't fixed, wasn't fixed in all cases or isn't the exact same bug but a different one that manifests the same way.
@DannyLane did you try the workaround of not using project and putting the computed expression directly into $group stage?
@AsyaKamsky I didn't try putting the computed expression directly in the group stage as I wanted to use the projected value multiple times (min, max, avg). I really wanted to get it setup in the project step and my answer above using .andExpression works for this.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.