1

I tried to write a group aggregation query using the year value from a date object as a key, but for some reason I'm getting this exception.

org.springframework.data.mapping.PropertyReferenceException: No property year(invoiceDate)

Here is the mongo query which I'm trying to replicate:

db.collection.aggregate([
   {
     $match:
     {
       "status": "Active"
     }
   },
   {
     $group:
     {
      "_id":{$year:"$invoiceDate"}
     }
  },
  {
    $sort:
    {
      "_id" : -1
    }
  }
])

And this is my Java implementation:

Aggregation aggregation = Aggregation.newAggregation(
    match(new Criteria().andOperator(criteria())),
    Aggregation.group("year(invoiceDate)")
).withOptions(newAggregationOptions().allowDiskUse(true).build());

I also didn't find a way how I can apply the sorting on the results from the grouping.

user134
  • 391
  • 2
  • 5
  • 15
  • `Aggregation.sort()` - Why would it be called anything else? – Neil Lunn May 18 '18 at 07:08
  • I thought that you need to supply a reference in the sort method, but you are probably right. Any thoughts why the SpEL expression fails? – user134 May 18 '18 at 07:55
  • The `Aggregation.sort()` didn't work, I got `You have to provide at least one property to sort by!` – user134 May 18 '18 at 08:19
  • Sorry, it was just a quick comment whilst I was walking away for a while and intended more as a "prompt" to pick up the method and discover the options. Added the actual pipeline translations below. – Neil Lunn May 18 '18 at 10:48
  • Is there something in the provided answer that you believe does not address your question? If so then please comment on the answer to clarify what exactly needs to be addressed that has not. If it does in fact answer the question you asked then please note to [Accept your Answers](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) to the questions you ask – Neil Lunn May 22 '18 at 09:55

1 Answers1

2

You're basically looking for extractYear() which maps to the $year operator with MongoDB:

Aggregation aggregation = Aggregation.newAggregation(
    Aggregation.match(new Criteria().andOperator(criteria())),
    Aggregation.project().and("invoiceDate").extractYear().as("_id"),
    Aggregation.group("_id"),
    Aggregation.sort(Sort.Direction.DESC, "_id)
)

This generally needs to go into a $project in order to make the helpers happy.

If you really want the expression within the $group then you can add a custom operation expression:

Aggregation aggregation = Aggregation.newAggregation(
  Aggregation.match(new Criteria().andOperator(criteria())),
  new AggregationOperation() {
    @Override
    public Document toDocument(AggregationOperationContext aggregationOperationContext) {
      return new Document("$group",
        new Document("_id", new Document("$year","$invoiceDate") )
      );
    }
  },
  Aggregation.sort(Sort.Direction.DESC, "_id)
)
Neil Lunn
  • 148,042
  • 36
  • 346
  • 317