mongodbspring-dataspring-data-mongodbspring-data-mongodb-reactive

Spring Data Reactive Mongo Operator how to call unset operation on nested field after performing lookup stage in an aggregate pipleine


I am merging records from two collections projects and card_types in an aggregation pipeline and then trying to remove the cardFields field of the merged record from the result. So the idea is that from the aggregate result which will be

{
   "projectId": "foo",
   ...
   "cardTypes": [
     {
        "itemId": "bar",
        "itemType": "Defect",
        "cardFields": [ { ... more objects here ...} ]
     },
     {
        ... more card types ...
     }
   ],
}

into

{
   "projectId": "foo",
   ...
   "cardTypes": [
     {
        "itemId": "bar",
        "itemType": "Defect"
        ...
     },
     {
        ... more card types ...
     }
   ],
}

The method I wrote is

public Flux<Document> getProjectDetails(String enterpriseId, String projectId) {
    AggregationOperation unset = UnsetOperation.unset("cardTypes.cardFields");
    return mongoOperations.aggregate(
            Aggregation.newAggregation(match(where(accountIdKeyName).is(enterpriseId).and(ownerIdKeyName).is(projectId)),
                    lookup("card_types", accountIdKeyName, accountIdKeyName, "cardTypes"),
                    unset), "project", Document.class);
}

The method fails with exception

org.springframework.data.mongodb.UncategorizedMongoDbException: Command failed with error 40324 (Location40324): 'Unrecognized pipeline stage name: '$unset''


Solution

  • Changed the method implementation to use $project instead

    public Flux<Document> getProjectDetails(String enterpriseId, String projectId) {
        List<AggregationOperation> pipeline = new ArrayList<>();
        pipeline.add(match(where(accountIdKeyName).is(enterpriseId).and(itemIdKeyName).is(projectId)));
        pipeline.add(context ->
                new Document("$lookup", new Document("from", "card_types")
                        .append("localField", "itemId")
                        .append("foreignField", "projectData.boardId")
                        .append("as", "cardTypes")
                ));
        pipeline.add(context ->
                new Document("$lookup", new Document("from", "swim_lanes")
                        .append("localField", "itemId")
                        .append("foreignField", "ownerId")
                        .append("as", "swimLanes")
                ));
        pipeline.add(context -> new Document("$project", new Document("_id", 0).append("cardTypes._id", 0)
                .append("cardTypes.cardFields", 0).append("swimLanes._id", 0)));
        return mongoOperations.aggregate(newAggregation(pipeline), "project", Document.class);
    }