java - 将操作分为两个级别,每个级别都有一个元素-数组关联

标签 java spring mongodb aggregation-framework spring-mongodb

我正在使用AngularJS前端和Java后端进行JHipster项目。我在MongoDB数据库中使用Spring Data。

我对名为budgetCode的字符串字段进行了分组操作。因此,对于每个budgetCode,都有一个链接的taskCodes列表,该列表是另一个String字段。我在另一个Stackoverflow帖子中成功做到了这一点:“对字段进行分组操作并将喜欢的字段的列表放入数组中”

在这里,方法aggregateAllTask​​Code进行分组操作:

储存库层

public class ClarityResourceAffectationRepositoryImpl implements ClarityResourceAffectationRepositoryCustom {
    @Autowired
    MongoTemplate mongoTemplate;

    @Override
    public List<ClarityResourceAffectationReport> aggregateAllTaskCode() {

        AggregationOperation project = new AggregationOperation() {
            @Override
            public DBObject toDBObject(AggregationOperationContext aggregationOperationContext) {
                return new BasicDBObject("$project", new BasicDBObject("budget_code", "$budget_code").append("task_code", Arrays.asList("$task_code")));
            }
        };

        Aggregation aggregation = newAggregation(project,
                group("budgetCode").addToSet("budgetCode").as("budgetCode").addToSet("taskCode").as("taskCode"),
                sort(Sort.Direction.ASC, previousOperation(),"budgetCode"));

        AggregationResults groupResults = mongoTemplate.aggregate(aggregation, ClarityResourceAffectation.class,
                ClarityResourceAffectationReport.class);
        List<ClarityResourceAffectationReport> clarityResourceAffectationReports = groupResults.getMappedResults();

        return clarityResourceAffectationReports;
    }
}


服务层

public class ClarityResourceAffectationServiceImpl implements ClarityResourceAffectationService{
    @Override
    public List<ClarityResourceAffectationReport> aggregateAllTaskCodes() {
        log.debug("Request to aggregateAllTaskCodes: {}");
        List<ClarityResourceAffectationReport> result = clarityResourceAffectationRepository
                .aggregateAllTaskCodes();

        return result;
    }
}


REST API层

public class ClarityResourceAffectationResource {
    @GetMapping("/clarity-resource-affectations/list-task-codes")
    @Timed
    public ResponseEntity<List<ClarityResourceAffectationReport>> aggregateTabAllTaskCodes() {
        log.debug("REST request to get aggregateTabAllTaskCodes : {}");
        List<ClarityResourceAffectationReport> result = clarityResourceAffectationService.aggregateAllTaskCodes();
        return new ResponseEntity<>(result, HttpStatus.OK);
    }
}


在这里,ClarityResourceAffectation和ClarityResourceAffectationReport文件:

清晰度资源影响

@Document(collection = "clarity_resource_affectation")
public class ClarityResourceAffectation implements Serializable {

    @Id
    private String id;

    @Field("budget_code")
    private String budgetCode;

    @Field("task_code")
    private String taskCode;

    @Field("action_code")
    private String actionCode;

    public String getBudgetCode() {
        return budgetCode;
    }

    public void setBudgetCode(String budgetCode) {
        this.budgetCode = budgetCode;
    }

    public String getTaskCode() {
        return taskCode;
    }

    public void setTaskCode(String taskCode) {
        this.taskCode = taskCode;
    }

    public String getActionCode() {
        return actionCode;
    }

    public void setActionCode(String actionCode) {
        this.actionCode = actionCode;
    }
}


ClarityResourceAffectationReport

public class ClarityResourceAffectationReport implements Serializable {

    private static final long serialVersionUID = 1L;

    private String[] budgetCodes;
    private String[][] taskCodes;
    private String[][][] actionCodes;

    public String[] getBudgetCodes() {
        return budgetCodes;
    }

    public void setBudgetCodes(String[] budgetCodes) {
        this.budgetCodes = budgetCodes;
    }

    public String[][] getTaskCodes() {
        return taskCodes;
    }

    public void setTaskCodes(String[][] taskCodes) {
        this.taskCodes = taskCodes;
    }

    public String[][][] getActionCodes() {
        return actionCodes;
    }

    public void setActionCodes(String[][][] actionCodes) {
        this.actionCodes = actionCodes;
    }
}


我在数据库中拥有的样本示例

/* 0 */
{
    "_class": "fr.bpce.kpi.clarity.domain.ClarityResourceAffectation",
    "budget_code": "P24DCDSA01",
    "task_code": "61427",
    "action_code": "354"
}
/* 1 */
{
    "_class": "fr.bpce.kpi.clarity.domain.ClarityResourceAffectation",
    "budget_code": "P24DCDSA01",
    "task_code": "61427",
    "action_code": "121"
}
/* 2 */
{
    "_class": "fr.bpce.kpi.clarity.domain.ClarityResourceAffectation",
    "budget_code": "P24DCDSA01",
    "task_code": "65434",
    "action_code": "143"
}
/* 3 */
{
    "_class": "fr.bpce.kpi.clarity.domain.ClarityResourceAffectation",
    "budget_code": "P24DCDSA01",
    "task_code": "65434",
    "action_code": "463"
}
/* 4 */
{
    "_class": "fr.bpce.kpi.clarity.domain.ClarityResourceAffectation",
    "budget_code": "P24PR00",
    "task_code": "60298",
    "action_code": "255"
}
/* 5 */
{
    "_class": "fr.bpce.kpi.clarity.domain.ClarityResourceAffectation",
    "budget_code": "P24PR00",
    "task_code": "60298",
    "action_code": "127"
}
/* 6 */
{
    "_class": "fr.bpce.kpi.clarity.domain.ClarityResourceAffectation",
    "budget_code": "P24PR00",
    "task_code": "67875",
    "action_code": "348"
}
/* 7 */
{
    "_class": "fr.bpce.kpi.clarity.domain.ClarityResourceAffectation",
    "budget_code": "P24PR00",
    "task_code": "67875",
    "action_code": "654"
}


目前,对于budgetCode ["P221P00"],我有一个链接的taskCodes [["2630"],["61297"],["61296"],["61299"]]的列表。我想在ClarityResourceAffectationReport文件String[][][]actionCode中添加第三个字段,以进行另一个分组级别。这样,taskCodes列表的每个元素都将链接到actionCode列表。在另一个Stackoverflow帖子中,Veeram建议我做两个小组,一个小组在budgetCodetaskCodes上推actionCode,另一小组在budgetCode上并推上一个小组的taskCodesactionCode

因此,我开发了一种具有两个项目操作和两个聚合操作的方法。我不确定是不是这样。另外,我不知道如何形成分组结果,因为现在我们有两个聚合操作。另外,我认为现在在ClarityResourceAffectationReport中,我有三个数组:String[] budgetCodes, String[][] taskCodes, String[][][] actionCodes

@Override
public List<ClarityResourceAffectationReport> aggregateAllBudgetCode() {

        //I did two projects instantiations
        AggregationOperation projectBudgetTask = new AggregationOperation() {
            @Override
            public DBObject toDBObject(AggregationOperationContext aggregationOperationContext) {
                return new BasicDBObject("$project", new BasicDBObject("budget_code", "$budget_code").append("task_code", Arrays.asList("$task_code")));
            }
        };

        AggregationOperation projectTaskAction = new AggregationOperation() {
            @Override
            public DBObject toDBObject(AggregationOperationContext aggregationOperationContext) {
                return new BasicDBObject("$project", new BasicDBObject("task_code", "$task_code").append("action_code", Arrays.asList("$action_code")));
            }
        };

        //I did two aggregation methods
        Aggregation aggregationBudgetTask = newAggregation(projectBudgetTask,
                group("budgetCode", "taskCode").addToSet("budgetCodeTaskCode").as("budgetCodeTaskCode").addToSet("actionCode").as("actionCode"),
                sort(Sort.Direction.ASC, previousOperation(),"budgetCode", "taskCode"));

        Aggregation aggregationTaskAction = newAggregation(projectTaskAction,
                group("budgetCode").addToSet("budgetCode").as("budgetCode").addToSet("taskCodes").as("taskCodes").addToSet("actionCode").as("actionCode"),
                sort(Sort.Direction.ASC, previousOperation(),"budgetCode"));        

        //Here, how can I put the two aggregation methods?
        AggregationResults groupResults = mongoTemplate.aggregate(aggregation, clarityResourceAffectation.class,
                ClarityResourceAffectationReport.class);
        List<ClarityResourceAffectationReport> clarityResourceAffectationReport = groupResults.getMappedResults();

        return clarityResourceAffectationReport ;
    }


在第一个聚合操作中,我做了一个group("budgetCode", "taskCode"),然后放了一个addToSet("budgetCodeTaskCode").as("budgetCodeTaskCode"),因为我想考虑一个分组操作。但是,实际上我想做的是group("budgetCode", "taskCode").addToSet("budgetCode", "taskCode").as("budgetCode", "taskCode")。但是,在addToSetas方法中,我们不能放置两个参数。那么,我们该怎么办?而且,如何将这两种聚合方法放在AggregationResults groupResults中?

我试过了,但是没有起作用

为了区分clarityResourceAffectationclarityResourceAffectationReport,我在报告类的每个字段处添加了一个“ s”字母。我更新了帖子。

在这里,我尝试了一种聚合操作的代码:

@Override
public List<ClarityResourceAffectationReport> aggregateAllTaskCode() {

    AggregationOperation project = new AggregationOperation() {
         @Override
         public DBObject toDBObject(AggregationOperationContext aggregationOperationContext) {
           return new BasicDBObject("$project", new BasicDBObject("task_code", "$task_code").append("action_code", Arrays.asList("$action_code")));
        }
    };

    Aggregation aggregation = newAggregation(project,
              group("budgetCode", "taskCode").addToSet("actionCode").as("actionCodes"),
              group("budgetCode").first("taskCode").as("taskCode").addToSet(new BasicDBObject("taskCode","$_id.taskCode").append("actionCodes", "$actionCodes")).as("taskCodes"),
              sort(Sort.Direction.ASC, previousOperation(),"taskCodes"));

    AggregationResults groupResults = mongoTemplate.aggregate(aggregation, ClarityResourceAffectation.class,
            ClarityResourceAffectationReport.class);
    List<ClarityResourceAffectationReport> clarityResourceAffectationReports = groupResults.getMappedResults();

    log.debug("clarityResourceAffectationReports.size()" + clarityResourceAffectationReports.size());
    log.debug("aggregation.toString()" + aggregation.toString());

    return clarityResourceAffectationReports;
}


我没有运行,并且出现错误:f.b.k.l.w.r.errors.ExceptionTranslator : Target bean of type [[Ljava.lang.String; is not of type of the persistent entity ([Ljava.lang.String;)!。无论如何,在代码中您也将.append("actionCodes", "actionCodes")).as("taskCodeActionCodes")放在第二组后面。您能解释什么是taskCodeActionCodes吗?

扁平结构的结果

我稍微更改了ResourceAffectationReport字段的类型:字符串budgetCodes,字符串[] taskCodes和字符串[] [] actionCodes。

[
  {
    "budgetCodes": "P24D001",
    "taskCodes": [
      "64578"
    ],
    "actionCodes": [
      [
        "454"
      ],
      [
        "253"
      ],
      [
        "745"
      ],
      [
        "354"
      ]
    ]
  },
  {
    "budgetCodes": "P24D002",
    "taskCodes": [
      "62678"
    ],
    "actionCodes": [
      [
        "857"
      ],
      [
        "907"
      ],
      [
        "858"
      ]
    ]
  }
]


地图结构的结果

在这里,报告文件的类型为String budgetCode,String [] taskCodes,String [] [] actionCodes,List> taskCodesActionCodes。

[
  {
    "budgetCodes": "P24D001",
    "taskCodes": null,
    "actionCodes": null,
    "taskCodesactionCodes": [
      {
        "[Ljava.lang.String;@7e695137": [
          [
            "64578"
          ]
        ],
        "[Ljava.lang.String;@48ec311a": [
          [
            "454"
          ],
          [
            "253"
          ],
          [
            "745"
          ],
          [
            "354"
          ]
        ]
      },
      {
        "[Ljava.lang.String;@258b30b6": [
          [
            "62678"
          ]
        ],
        "[Ljava.lang.String;@481154c7": [
          [
            "857"
          ],
          [
            "907"
          ],
          [
            "858"
          ]
      }
    ]
  },
  {
    "budgetCodes": "P24D002",
    "taskCodes": null,
    "actionCodes": null,
    "taskCodesActionCodes": [
      {
        "[Ljava.lang.String;@1cdf4a9e": [
          [
            "64568"
          ]
        ],
        "[Ljava.lang.String;@1613fdbb": [
          [
            "764"
          ],
          [
            "984"
          ],
          [
            "489"
          ]
        ]
      },
      {
        "[Ljava.lang.String;@53167f62": [
          [
            "63887"
          ]
        ],
        "[Ljava.lang.String;@5a30c8de": [
          [
            "757"
          ],
          [
            "394"
          ],
          [
            "294"
          ],
          [
            "765"
          ]
        ]
      }
    ]
  }
]


地图结构方法很有趣,但是我有一些问题要在前端显示,但是由于键是对象类型,这是另一个问题。我会再次测试,然后告诉您。无论如何,这很有趣。实际上,我有另一个想法。我想要的是在每个JSON文档中我都有一个String字段budgetCodes,一个String []字段taskCodes,其中将包含所有
将taskCodes链接到budgetCodes,我认为最终真正适合我想要的是创建一个像这样的TaskCode类:

public class TaskCode {
    private String taskCode;
    private String[] actionCode;

    //Getters and Setters
}


通过这种方式,它将允许我为每个JSON文档使用一个带有budgetCode的简单字符串,一个链接的TaskCodes列表,用于
每个taskCode对象,即String属性taskCode,其中将包含taskCode的值。最后,每个taskCode对象将包含一个String []
与actionCodes列表。

关于POJO结构

它运行良好,但为了在AngularJS前端中显示数据,我遇到了一些问题。我想进行聚合操作,以创建一个菜单,在该菜单中,每次单击元素都会打开一个带有子列表的子菜单,依此类推,依此类推……我不知道聚合是否真的适应了我想做的事。因此,我想到了另一种方法。除了执行聚合操作外,另一种方法可能是通过数据库中的简单查找操作检索我想要的数据,并使用服务层来执行树算法。

提前致谢

最佳答案

您可以在单个聚合管道中执行多个级别分组。

更新了现有项目阶段以包括actionCode,并更新了现有组以包括actionCode

这将显示扁平化的结构,每行包含budgetCodestaskCodesactionCodes

将您的actionCodes更新为private String[][] actionCodes;

平面结构。

就像是

 AggregationOperation project = new AggregationOperation() {
   @Override
    public DBObject toDBObject(AggregationOperationContext aggregationOperationContext) {
         return new BasicDBObject("$project", new BasicDBObject("budget_code", 1).append("task_code",  Arrays.asList("$task_code")).append("action_code", Arrays.asList("$action_code")));
       }
    };

Aggregation aggregation = newAggregation(project,
         group("budgetCode", "taskCode").addToSet("actionCode").as("actionCodes"),
         project("actionCodes").and("_id.budgetCode").as("budgetCodes").and("_id.taskCode").as("taskCodes").andExclude("_id"),
         sort(Sort.Direction.ASC, "budgetCodes","taskCodes"));


像结构一样映射。

将输出DTO调整为

private String[] budgetCodes;
private List<Map<String[], String[][]>> taskCodeActionCodes;


这会将结果输出到Map中,从而为您提供多个分组。

就像是

AggregationOperation project = new AggregationOperation() {
  @Override
  public DBObject toDBObject(AggregationOperationContext aggregationOperationContext) {
       return new BasicDBObject("$project", new BasicDBObject("budget_code", 1).append("task_code",  Arrays.asList("$task_code")).append("action_code", Arrays.asList("$action_code")));
     }
  };

Aggregation aggregation = newAggregation(project,
         group("budgetCode", "taskCode").addToSet("actionCode").as("actionCodes"),
         group("_id.budgetCode").addToSet(new BasicDBObject("taskCode","$_id.taskCode").append("actionCodes", "$actionCodes")).as("taskCodeActionCodes"),
            project("taskCodeActionCodes").and("budgetCodes").previousOperation().andExclude("_id"),
         sort(Sort.Direction.ASC, "budgetCodes"));


POJO结构

public class ClarityResourceAffectationReport {

    private String budgetCode;
    private List<TaskCode> linkedTaskCodes;
}


public class TaskCode {
    private String taskCode;
    private String[] actionCode;

}

Aggregation aggregation = newAggregation(
          group("budgetCode", "taskCode").addToSet("actionCode").as("actionCode"),
          group("_id.budgetCode").addToSet(new BasicDBObject("taskCode","$_id.taskCode").append("actionCode", "$actionCode")).as("linkedTaskCodes"),
               project("linkedTaskCodes").and("budgetCode").previousOperation().andExclude("_id"),
         sort(Sort.Direction.ASC, "budgetCode"));

关于java - 将操作分为两个级别,每个级别都有一个元素-数组关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44503200/

相关文章:

Javascript 包含方法不适用于 MongoDB ID

c++ - 如何通过mongocxx C++驱动上传MongoDB中的文件?

mongodb - 蒙戈 : show dbs doesn't show the test db. 为什么?

java - 如果使用 spring + stomp + 带有rabbitmq的完整代理,如何自动删除队列

java - 如何在Spring Webflux中为所有请求添加查询参数

java - 从 Firefox 扩展的 Javascript 访问 Java 类时遇到问题

java - 如何在本地构建中触发 yaml 文件的处理?

java - Spring 集成 : Not able to send the message to channel

java - 背景图像和文本的布局管理器

java - TestNG Listener 的 TestNG BeforeClass 和 AfterMethod 等效方法