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

Posted

技术标签:

【中文标题】将 mongo 查询转换为 spring-data-mongo 查询【英文标题】:translate mongo query to spring-data-mongo query 【发布时间】:2022-01-17 04:32:05 【问题描述】:

我有一个使用 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

【问题讨论】:

【参考方案1】:

您使用的是哪个版本的 Spring Data 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 类中不可用,但可以直接使用。

【讨论】:

【参考方案2】:

正如您所观察到的,Spring-Data 不允许定义所有合法的 MongoDB 查询。 但是,你可以做一个技巧:

所有 Spring-Data AggregationOperation 实现(MatchOperationAggregationOperation、...)都变为 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

【讨论】:

以上是关于将 mongo 查询转换为 spring-data-mongo 查询的主要内容,如果未能解决你的问题,请参考以下文章

将Mongo查询转换为spring Mongooperations

将 SQL 查询转换为 Mongo 聚合

将 $facet mongo 查询转换为 Spring Data

Neo4j 和 Spring-data Map 查询结果到 Jackson JsonNode

简单oracle 查询语句 转换为 mongo 查询语句

@Indexed 嵌套属性在 mongo 的 Spring-data 中不起作用