6

I'm running a MongoDB aggregation where the last stage is a $merge that writes some field to another collection. Basically, this $merge should make an effect only on a single document (this is why we have on: "_id".

Here's how I do it with Java:

var merge = Aggregation.merge().intoCollection("items")
                .on("_id")
                .whenMatched(MergeOperation.WhenDocumentsMatch.mergeDocuments())
                .whenNotMatched(MergeOperation.WhenDocumentsDontMatch.discardDocument())
                .build();

var agg = Aggregation.newAggregation(match, group, merge);
var aggResult = mongoTemplate.aggregate(agg, "prices", Item.class);
  

The aggregation does what it needs and I can see that the requested document has changed, but the problem is that aggregate() returns all the documents in the collection.

This is a major drawback and can't scale well when the collection is large enough.

How can I change my query so it will return only the changed document. Or if not possible, just apply the query without returning anything.

IsaacLevon
  • 2,260
  • 4
  • 41
  • 83
  • Apparently you made some assumptions about how the Spring implementation of the Aggregation Pipeline operates which were inaccurate. Here you are calling it a problem, but it returns results by design, which by definition is not a problem, it is a feature. As you found, an option allows turning off return of the data (skipOutput()) which is included in the online documentation (https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/aggregation/AggregationOptions.Builder.html#skipOutput--). Your question appears hostile which is rarely helpful. – barrypicker Aug 19 '21 at 17:52
  • 2
    @barrypicker, thanks for your comment but I'm shocked you see my question as hostile. Heck, I even added an answer for the help of future readers. By the way, when I ran the same query from a MongoDB IDE I got a message that the query ran successfully but didn't return any output so I assumed someone is inconsistent with the aggregation API – IsaacLevon Aug 20 '21 at 08:20
  • This drove me crazy and cost me like one full working day. My aggregation ends with some merge and in Robo3T it returns no results therefore and just does its work. I even limit the aggregation to small batches and still my application ran OutOfMemory with the big unused result datasets. Glad I found the .skipOutput option finally. There should be directly a void mongoTemplate.aggregate method without Return Type for such cases. Big pit fall... – Ralf Aug 17 '23 at 15:47

1 Answers1

6

Found the answer and will share for future readers:

mongoTemplate.aggregate(aggregation.withOptions(newAggregationOptions().skipOutput().allowDiskUse(true).build()), "collectionNme", EntityClass.class);
IsaacLevon
  • 2,260
  • 4
  • 41
  • 83