5

Mongo document:

{
    "_id" : "1",
    "array" : [
        {
            "item" : "item"
        }, 
        {
            "item" : "item"
        }
    ]
}

My mongo shell query looks like so:

db.getCollection('collectionName').aggregate(
    {$match: { _id: "1"}},
    {$project: { count: { $size:"$array" }}}
)

Is there anyway to implement this using the Mongo Template from Spring?

So far I have this:

MatchOperation match = new MatchOperation(Criteria.where("_id").is("1"));
ProjectionOperation project = new ProjectionOperation();
Aggregation aggregate = Aggregation.newAggregation(match, project);
mongoTemplate.aggregate(aggregate, collectionName, Integer.class);

I think I am only missing the project logic but I'm not sure if it is possible to do $size or equivalent here.

3 Answers 3

6

It's quite possible, the $size operator is supported (see DATAMONGO-979 and its implementation here). Your implementation could follow this example:

import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;

Aggregation agg = new Aggregation(
    match(where("_id").is("1")), //  
    project() //
        .and("array") //
        .size() //
        .as("count")
);

AggregationResults<IntegerCount> results = mongoTemplate.aggregate(
    agg, collectionName, Integer.class
);
List<IntegerCount> intCount = results.getMappedResults();
Sign up to request clarification or add additional context in comments.

3 Comments

That 'where' is now Criteria.where( ... )
Where does the IntegerCount came form? Is this only a POJO with attributes _id and count ?
Note: if you just want the int count so you can return it from a method, you can get it out with this results.getUniqueMappedResult().getInteger("count"). (You must change IntegerCount.class above to org.bson.Document.class)
1

Please find below the sample code. You can change it accordingly for your requirement with collection name, collection name class and array field name.

    MatchOperation match = new MatchOperation(Criteria.where("_id").is("1"));
    Aggregation aggregate = Aggregation.newAggregation(match, Aggregation.project().and("array").project("size").as("count"));

    AggregationResults<CollectionNameClass> aggregateResult = mongoOperations.aggregate(aggregate, "collectionName", <CollectionNameClass>.class);

    if (aggregateResult!=null) {
        //You can find the "count" as an attrribute inside "result" key
        System.out.println("Output ====>" + aggregateResult.getRawResults().get("result"));
        System.out.println("Output ====>" + aggregateResult.getRawResults().toMap());
    }

Sample output:-

Output ====>[ { "_id" : "3ea8e671-1e64-4cde-bd78-5980049a772b" , "count" : 47}]
Output ====>{serverUsed=127.0.0.1:27017, waitedMS=0, result=[ { "_id" : "3ea8e671-1e64-4cde-bd78-5980049a772b" , "count" : 47}], ok=1.0}

Comments

0

You can write query as

 Aggregation aggregate = Aggregation.newAggregation(Aggregation.match(Criteria.where("_id").is(1)),
            Aggregation.project().and("array").size().as("count")); mongoTemplate.aggregate(aggregate, collectionName, Integer.class);

It will execute the following query { "aggregate" : "collectionName" , "pipeline" : [ { "$match" : { "_id" : 1}} , { "$project" : { "count" : { "$size" : [ "$array"]}}}]}

Comments

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.