1

I want to create an aggregation Query using spring data mongodb.

My collection data structure is:

{
    date: ISODate("2022-12-11T01:13:00.000Z"),
    metadata: {
        homeId: '51b87ea3d846f450141ae58z',
        nodeId: '51b87ea3d846f450141ae58z'
    },
    value: 42,
    _id: ObjectId("63b583e30c1e523313b64ed5")
}

The MongoDb Query that I want to translate to java is:

db.consumptions.aggregate(
[
    { $match : {"metadata.nodeId": "51b87ea3d846f450141ae58z"}
    },
    { $project: { 
        date: { 
            $dateToParts: { date: "$date"}
            }, 
        value: 1
        }
    },
    { $group: { 
        _id: { 
            date: { 
                year: "$date.year", month: "$date.month", day: "$date.day"
            }
        }, 
        cumulValue: { $sum: "$value"}
        }
    },
    { $sort : { "_id.date": -1}
    }
]
)

The MongoDb Query result looks like this:

[
    {
        _id: { 
            date: { year: 2022, month: 12, day: 11 } 
        },
        cumulValue: 42 
    }
]

So as you can see here, the result structure is _id with a nested object date containing fields year, month and day.

I would like to have the same result _id structure using groupOperation with spring data mongo.

I tried this implementation

MatchOperation matchOperation = Aggregation.match(
    new Criteria().andOperator(Criteria.where("metadata.nodeId").is(nodeId);
        
// projection Operation
ProjectionOperation projectionOperation = project("value")
    .and(DateOperators.dateOf("date").toParts()).as("date");

// group Operation
GroupOperation groupOperation = Aggregation.group(
    "date.year", "date.month", "date.day")
    .sum("value").as("cumulativeValue");
        
// Sort Operation
SortOperation sortOperation = sort(pageRequest.getSort());

Aggregation aggregation = Aggregation.newAggregation(
    matchOperation, projectionOperation, groupOperation,sortOperation);

But I'm not able to have the expected result structure (with nested object date)

{
    _id: {
      year: 2022,
      month: 11,
      day: 11
    },
    cumulValue: 284
}

1 Answer 1

1

You can try this by parsing the entire pipeline string.

String groupStage = "{\r\n" + 
        "    $group: {\r\n" + 
        "      _id: {\r\n" + 
        "        date: {\r\n" + 
        "          year: \"$date.year\",\r\n" + 
        "          month: \"$date.month\",\r\n" + 
        "          day: \"$date.day\"\r\n" + 
        "        }\r\n" + 
        "      },\r\n" + 
        "      cumulValue: {\r\n" + 
        "        $sum: \"$value\"\r\n" + 
        "      }\r\n" + 
        "    }\r\n" + 
        "  }"

GroupOperation groupOperation = context -> context.getMappedObject(Document.parse(groupStage));
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the suggestion , I'll try this. I'm just wondering if it does represent any performance issue ?

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.