Search code examples
spring-data-mongodbspring-mongospring-mongodb

How to use mongodb aggregate functions in Criteria?


I am working on a project where I use spring data mongodb. I am making a mongo query like this:

Query query = new Query();

Criteria one = Criteria.where(DB_FIELD_1).gt(1);
Criteria two = Criteria.where(DB_FIELD_2).lt(10);

Criteria final = new Criteria().andOperator(one,two);
query.addCriteria(final);

// after making the query, I am executing it using mongoTemplate

Now, I have a Date field with format YYYYMMDD. I would like to check if its month = current month. For example, if the field is 20170501, then the date's month (05) is current month (5, May). How do I extract the month value from date and check this logic along with other criteria above ( one and two )? I know there is $month to extract the month value from date. But, I do not know how to incorporate aggregate function within "Criteria" class. My final result should be something like this:

 Criteria final = new Criteria().andOperator(one,two,criteria to check month = current month);
 query.addCriteria(final);

Solution

  • You can use below aggregation pipeline with the current spring db version 1.10.2/ Spring 1.5.2 Boot. Include the other fields in the $project that you wish to output.

    Use $addFields instead of $project for 3.4 x mongo server version.

     AggregationOperation project = Aggregation.project().and(DateOperators.dateOf(DB_FIELD_1).month()).as("field1").and(DateOperators.dateOf(DB_FIELD_2).month()).as("field2");
     AggregationOperation match = Aggregation.match(Criteria.where("field1").gt(1)
                    .and("field2").lt(10));
     Aggregation aggregation = Aggregation.newAggregation(project, match);
     List<BasicDBObject> results = mongoTemplate.aggregate(aggregation, collectionname, BasicDBObject.class).getMappedResults();
    

    Use for 1.4.1 version

    AggregationOperation project = Aggregation.project().and(DB_FIELD_1).extractMonth().as("field1").and(DB_FIELD_2).extractMonth().as("field2");