james
james

Reputation: 275

How to sum the array size across the entire collection?

I have the mongodb json data:

{
    "_id" : ObjectId("1111111111111111"),
    "teamId" : "111",
    "scoreId" : "50dcefb52d764ca3913985a80a4162ef",
    "utterances" : [ 
        {
            "text" : "test1",
            "parsedText" : "test1"
        }, 
        {
            "text" : "test2",
            "parsedText" : "test2"
        }
        
    ]
   
},
{
    "_id" : ObjectId("22222222222222"),
    "teamId" : "111",
    "scoreId" : "60dcefb52d764ca3913985a80a4162ef",
    "utterances" : [ 
        {
            "text" : "do it1",
            "parsedText" : "do it1"
        }, 
        {
            "text" : "do it2",
            "parsedText" : "do it2"
        },
        {
            "text" : "do it3",
            "parsedText" : "do it3"
        }
        
    ]
   
}

And mongo query is like:

db.teamScore.aggregate([
  {$match : {teamId:"111"}},
  {$unwind: '$utterances'},
  {$group: {_id: '$_id', 'sum': { $sum: 1}}},
  {$group: {_id: null, total_sum: {'$sum': '$sum'}}}
])
===>5

What I want to do is that total sum utterances using spring mongo aggregation

I am trying to make a source like:

Criteria creteria = Criteria.where("teamId").is("111");
MatchOperation matchStage = Aggregation.match(creteria);
GroupOperation group = group("scoreId")
        .push("$utterances").as("utterances");

ProjectionOperation projectStage = project().and("scoreId").arrayElementAt(0).as("scoreId")
        .and("utterances").size().as("count");

Aggregation aggregation = Aggregation.newAggregation(matchStage, unwind("utterances", true),  group, projectStage);
AggregationResults<Intent> result = mongoTemplate.aggregate(aggregation, "intents", Intent.class);
List<Intent> results = result.getMappedResults();

How can I count utterances? I am new to mongodb so give me a tip to solve this problem. aggregation is best way to count array list,right?

Upvotes: 2

Views: 1403

Answers (2)

s7vr
s7vr

Reputation: 75964

You can simplify your aggregation to below.

db.teamScore.aggregate([
  {$match : {teamId:"111"}},
  {$group: {_id: null, "total_sum": {"$sum": {"$size":"$utterances"}}}}
])

Spring code:

Criteria creteria = Criteria.where("teamId").is("111");
MatchOperation matchStage = Aggregation.match(creteria);
GroupOperation group = group()
               .sum(ArrayOperators.Size.lengthOfArray("utterances")).as("count");
Aggregation aggregation = Aggregation.newAggregation(matchStage, group);
AggregationResults<Intent> result = mongoTemplate.aggregate(aggregation, "intents", Intent.class);
List<Intent> results = result.getMappedResults();

Upvotes: 2

pvpkiran
pvpkiran

Reputation: 27068

Here is one way to do it

Criteria criteria = Criteria.where("teamId").is("111");
MatchOperation matchOperation = match(criteria);
AggregationExpression aggregationExpression =  
                                    ArrayOperators.Size.lengthOfArray("utterances");
ProjectionOperation projectionOperation =   
                  project("scoreId", "teamId").and(aggregationExpression).as("sum");

GroupOperation groupOperation = group("teamId").sum("sum").as("totalSum");
Aggregation aggregation = Aggregation.newAggregation(matchOperation, projectionOperation, groupOperation);
AggregationResults<BasicDBObject> team = mongoTemplate.aggregate(aggregation, "team", BasicDBObject.class);

Instead of BasicDBObject you can use your pojo and map the fields.

Upvotes: 0

Related Questions