Execute MongoTemplate.aggregate without row retrival
Asked Answered
D

2

4

I'm using the Spring Mongo driver to execute a large mongo aggregation statement that will run for a period of time. The output stage of this aggregation writes the output of the aggregation into a new collection. At no point do I need to retrieve the results of this aggregation in-memory.

When I run this in Spring boot, the JVM is running out of memory doing row retrieval, although I'm not using or storing any of the results.

Is there a way to skip row retrieval using MongoTemplate.aggregate?

Ex:

mongoTemplate.aggregate(Aggregation.newAggregation(
   Aggregation.sort(new Sort(new Sort.Order(Sort.Direction.DESC, "createdOn"))),

   Aggregation.group("accountId")
      .first("bal").as("bal")
      .first("timestamp").as("effectiveTimestamp"),

   Aggregation.project("_id", "effectiveTimestamp")
                        .andExpression("trunc(bal * 10000 + 0.5) / 100").as("bal"),

   aggregationOperationContext -> new Document("$addFields", new Document("history",Arrays.asList(historyObj))),

   // Write results out to a new collection - Do not store in memory
   Aggregation.out("newBalance")
).withOptions(Aggregation.newAggregationOptions().allowDiskUse(true).build()),
   "account", Object.class
);
Downall answered 25/2, 2020 at 19:55 Comment(2)
>Is there a way to skip row retrieval using MongoTemplate.aggregate? - I fear, not (when you ask that strict). ..and the problem is maybe not with Aggregation.out, but Arrays.asList() ...? 1. how large is historyObj? 2. have a stacktrace? ...increasing memory is of course "always worth"Pralltriller
Arrays.asList(historyObj) will always be a 1 element array that's used to build this queryDownall
D
0

I was able to resolve this by using

MongoTempalte.aggregateStream(...).withOptions(Aggregation.newAggregationOptions().cursorBatchSize(0).build)
Downall answered 26/2, 2020 at 20:11 Comment(0)
W
5

Use AggregationOption - skipOutput() . This will not return a result in case of aggregation pipeline contains $out/$merge operation.

mongoTemplate.aggregate(aggregation.withOptions(newAggregationOptions().skipOutput().allowDiskUse(true).build()), "collectionNme", EntityClass.class);

If you are using MongoDriver without framework.

MongoClient client = MongoClients.create("mongodb://localhost:27017");
 MongoDatabase database = client.getDatabase("my-collection");
 MongoCollection<Document> model = database.getCollection(collectionName);
 AggregateIterable<Document> aggregateResult = model.aggregate(bsonListOfAggregationPipeline);
 
 // instead iterating over call toCollection() to skipResult
 aggregateIterable.toCollection();

References:

Wrens answered 14/4, 2021 at 8:23 Comment(0)
D
0

I was able to resolve this by using

MongoTempalte.aggregateStream(...).withOptions(Aggregation.newAggregationOptions().cursorBatchSize(0).build)
Downall answered 26/2, 2020 at 20:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.