将 mongo 查询转换为 spring-data-mongo 查询

translate mongo query to spring-data-mongo query

我有一个使用 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
            }
          }
        },
        
      ],
      
    }
  }
])

我很难将其转换为 spring-data-mongo 聚合对象!

更准确地说:

$$ROOT 变量似乎在 spring-data 中不起作用! 另外, $set 和 $unset 似乎不受支持? 最后,对于方面,我可以生成 data[] 部分,但无法生成计数:{ total: xx}

如您所见,Spring-Data 不允许定义所有合法的 MongoDB 查询。
但是,你可以玩个把戏:

所有 Spring-Data AggregationOperation 实现(MatchOperation, AggregationOperation, ...)变成 org.bson.Document.
您需要做的就是使用 MongoDB JSON 查询实现 AggregationOperation

  • 调用生成器:new Document("$unwind", "$tasks")
  • 来自 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

您使用的 Spring 数据 MongoDB 是哪个版本?对于 2.5.0 版,每个操作都按以下方式进行。

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 和 Unset 在 Aggregation 中不可用 class 但可以直接使用。