这是我想要根据一个命名对象创建的group操作。
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参数中提供了一个subDepartmentCode和一个mongo,下面是要执行的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现在是一个字符串,而不是一个命名对象。
即使只有一个字段,也可以强制group方法使用一个对象作为结果_id字段吗?或者,有没有其他方法来构建这样的mongo群组操作?
=================================================================
找到这个问题的“原因”。下面是spring data中的一段代码,它将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结果值。
发布于 2020-08-04 18:11:32
最后,目前可行的解决方案是创建一个管理文档转换_id部件的自定义AggregationOperation:
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似乎已被弃用。
https://stackoverflow.com/questions/63230160
复制相似问题