Home > Mobile >  translate mongo query to spring-data-mongo query
translate mongo query to spring-data-mongo query

Time:12-15

I have a query crafted with mongoPlayground here.

db.Workflow.aggregate([
  {
    $match: {}
  },
  {
    $unwind: "$tasks"
  },
  {
    "$addFields": {
      "workflow": "$$ROOT"
    }
  },
  {
    "$project": {
      workflowTask: "$tasks",
      workflow: "$workflow"
    }
  },
  {
    $set: {
      "workflowTask.workflow": "$workflow"
    }
  },
  {
    $unset: [
      "workflowTask.workflow.tasks",
      "workflow",
      "_id"
    ]
  },
  {
    $facet: {
      data: [
        {
          $skip: 0
        },
        {
          $limit: 30
        },
        
      ],
      count: [
        {
          $group: {
            _id: null,
            total: {
              $sum: 1
            }
          }
        },
        
      ],
      
    }
  }
])

I have a hard time converting this to spring-data-mongo Aggregation Objects!

To be more precise:

  • match is fine
  • unwind is fine
  • project is fine

it seems the $$ROOT variable is not working in spring-data! Also, $set and $unset seems unsupported? And finally, for the facet, i can produce the data[] part, but unable to produce the count:{ total: xx}

CodePudding user response:

Which version of Spring Data MongoDB are you using? With version 2.5.0, each operation works the following way.

MatchOperation matchOperation = Aggregation.match(new Criteria());
UnwindOperation unwindOperation = Aggregation.unwind("tasks");
AddFieldsOperation addFieldsOperation = Aggregation.addFields().addField("workflow").withValue("$$ROOT").build();
ProjectionOperation projectionOperation = Aggregation.project("_id").and("tasks").as("workflowTask").and("workflow").as("workflow");
SetOperation setOperation = SetOperation.builder().set("workflowTask.workflow").toValueOf("workflow");
UnsetOperation unsetOperation = UnsetOperation.unset("workflowTask.workflow.tasks", "workflow", "_id");
FacetOperation facetOperation = Aggregation.facet()
        .and(Aggregation.skip(0L), Aggregation.limit(30))
        .as("data")
        .and(Aggregation.group().count().as("total"))
        .as("count");

Set and Unset are not available in Aggregation class but they can be used directly.

CodePudding user response:

As you have observed, Spring-Data does not allow defining all legitimate MongoDB queries.
But, you can do a trick:

All Spring-Data AggregationOperation implementations (MatchOperation, AggregationOperation, ...) turns into org.bson.Document.
All you need to do is implement AggregationOperation with MongoDB JSON query:

  • Calling builder: new Document("$unwind", "$tasks")
  • From JSON: Document.parse("{\"$unwind\": \"$tasks\"}")

// Define aggregation pipelines
List<AggregationOperation> pipeline = new ArrayList<>();

//$addFields
pipeline.add(Aggregation.addFields().addFieldWithValue("workflow", "$$ROOT").build());

//$unset
pipeline.add(agg -> new Document("$unset", 
    Arrays.asList(
        "workflowTask.workflow.tasks",
        "workflow",
        "_id")));

//$facet
pipeline.add(agg -> new Document("$facet", ...))

AggregationOperation

  • Related