Search code examples
mongodbaggregation-frameworkspring-data-mongodbmongotemplate

How to reduce mongoDB queries


I have following sample data in mongoDB collection

{
  "version": "1.1",
  "platformName": "A",
  "uri": "https://example.com/1e2b59da-44c1-44a4-aa03-b4487bde0c71"
}

{
  "version": "1.1",
  "platformName": "B",
  "uri": "https://example.com/1e2b59da-44c1-44a4-aa03-b4487bde0c72"
}

{
  "version": "1.1",
  "platformName": "A",
  "uri": "https://example.com/1e2b59da-44c1-44a4-aa03-b4487bde0c73"
}

I am getting count of platformName by value by using basic query and aggregation. E.g. platform A has 2 count, while platform B has only one count.

public List<CountDto> groupByFieldName(String fieldName, BasicQuery basicQuery) {
    basicQuery.fields().include("id");
    List<LcaProduct> lcaProductList = mongoTemplate.find(basicQuery, LcaProduct.class, "sample_collection");
    List<String> productNames = lcaProductList.parallelStream().map(lcaProduct -> lcaProduct.getPlatformName()).collect(Collectors.toList());
    Aggregation aggregation = newAggregation(
            match(Criteria.where("platformName").in(productNames)),
            group(fieldName)
                    .first(fieldName).as("name")
                    .count().as("count")
    );
    AggregationResults<CountDto> results = mongoTemplate.aggregate(aggregation, "sample_collection", CountDto.class);
    return results.getMappedResults();
}

I have to use two queries, first to get all products using basicQuery and second query which uses aggregation to match ids which I got as result of first query.

I want to get the required results using single query. Is is possible to execute aggregation along with basic query?


Solution

  • You can prepend your initial query to the aggregation.

    public List<CountDto> groupByFieldName(String fieldName, BasicQuery basicQuery) {
        
        Aggregation aggregation = newAggregation(
                match(ctx -> basicQuery.getQueryObject()),
                group(fieldName)
                        .first(fieldName).as("name")
                        .count().as("count")
        );
        AggregationResults<CountDto> results = mongoTemplate.aggregate(aggregation, "sample_collection", CountDto.class);
        return results.getMappedResults();
    }