mongodb - 如何在单个字段上创建 Spring Data MongoDB GroupOperation,但结果 id 为对象?
问题描述
这是我要根据命名对象创建的组操作。
private static GroupOperation createStatsGroupOperationFromNomenclature(Nomenclature nomenclature) {
Fields groupFields = Fields.fields("departmentCode");
nomenclature.getDepartmentCode().ifPresent(code -> groupFields.and("subDepartmentCode"));
nomenclature.getSubDepartmentCode().ifPresent(code -> groupFields.and("categoryCode"));
nomenclature.getCategoryCode().ifPresent(code -> groupFields.and("subCategoryCode"));
return group(groupFields)
.count().as("nbProducts")
.sum("$proposedMatchesAmount").as("nbProposedMatches")
.sum("$reviewedMatchesAmount").as("nbReviewedMatches");
}
departmentCode
如果我在 nomenclature 参数中提供 a和 a ,则使用前面的函数subDepartmentCode
,这是执行的 mongo 查询:
{
_id: {
"departmentCode": "$departmentCode",
"subDepartmentCode": "$subDepartmentCode"
},
"nbProduct": {
$sum: 1
},
"proposedMatchesAmount": {
$sum: "$proposedMatchesAmount"
},
"reviewedMatchesAmount": {
$sum: "$reviewedMatchesAmount"
}
}
此查询的结果在以下对象中解析:
@Builder
@Value
public class ProductsStatsDocument {
@Id
Nomenclature nomenclature;
Integer nbProducts;
Integer nbProposedMatches;
Integer nbReviewedMatches;
}
当我只departmentCode
在命名参数中提供一个时,问题就会出现。然后构建的组操作具有以下 mongo 查询语言等效项:
{
_id: "$departmentCode",
"nbProduct": {
$sum: 1
},
"proposedMatchesAmount": {
$sum: "$proposedMatchesAmount"
},
"reviewedMatchesAmount": {
$sum: "$reviewedMatchesAmount"
}
}
并且此查询的结果无法解析为之前ProductsStatsDocument
的结果,因为结果_id
字段 id 现在是 String 而不是 Nomenclature 对象。
即使只有一个字段,是否可以强制group
方法使用对象作为结果_id
字段?或者有没有其他方法来建立这样一个 mongo 组操作?
==================================================== ================
找到了这个问题的“原因”。这是一段来自 spring 数据的代码,它将 GroupOperation 转换为 bson 对象:
} else if (this.idFields.exposesSingleNonSyntheticFieldOnly()) {
FieldReference reference = context.getReference((Field)this.idFields.iterator().next());
operationObject.put("_id", reference.toString());
} else {
这是exposesSingleNonSyntheticFieldOnly
方法:
boolean exposesSingleNonSyntheticFieldOnly() {
return this.originalFields.size() == 1;
}
正如你所看到的,只要只有一个字段可以分组,它就会被用作_id
结果值。
解决方案
因此,目前似乎可行的最终解决方案是创建一个自定义 AggregationOperation 来管理文档转换_id
部分:
public class ProductsStatsGroupOperation implements AggregationOperation {
private static GroupOperation getBaseGroupOperation() {
return group()
.count().as("nbProducts")
.sum("$proposedMatchesAmount").as("nbProposedMatches")
.sum("$reviewedMatchesAmount").as("nbReviewedMatches");
}
private final Nomenclature nomenclature;
public ProductsStatsGroupOperation(Nomenclature nomenclature) {
this.nomenclature = nomenclature;
}
@Override
public Document toDocument(AggregationOperationContext context) {
Document groupOperation = getBaseGroupOperation().toDocument(context);
Document operationId = new Document();
for (Field field : getFieldsToGroupOn()) {
FieldReference reference = context.getReference(field);
operationId.put(field.getName(), reference.toString());
}
((Document)groupOperation.get("$group")).put("_id", operationId);
return groupOperation;
}
private Fields getFieldsToGroupOn() {
Fields groupFields = Fields.fields("departmentCode");
if (nomenclature.getDepartmentCode().isPresent()) {
groupFields = groupFields.and("subDepartmentCode");
}
if (nomenclature.getSubDepartmentCode().isPresent()) {
groupFields = groupFields.and("categoryCode");
}
if (nomenclature.getCategoryCode().isPresent()) {
groupFields = groupFields.and("subCategoryCode");
}
return groupFields;
}
}
这个解决方案有一个不好的地方:toDocument
似乎不推荐使用覆盖的方法。
推荐阅读
- python - Matplotlib 中散点图的不同标签
- php - 为什么将集合集合展平为所有数组值的数组?
- python - 错误:命令错误退出状态 1:python setup.py egg_info 检查日志以获取完整命令输出,同时 pip 安装遗传算法
- julia - 如何在 Julia 中制作 inf 矩阵?
- android - 无法在 android 11 中捕获图像
- python - 使用 Python Jenkins 我向 xml 文件添加了新参数,但它不更新配置
- reactjs - 我如何从 React 应用程序“外部化”material-ui
- shopify - 整个页面顶部的剖面层
- drag-and-drop - vuetify-如何在文本区域内更改 vuetify 中的箭头颜色和图标大小?
- javascript - 尝试使用 Contentful 将帖子列表添加到我的主页而不是 Gatsby 中的单独页面