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", ...))