在使用 MongoTemplate 进行分组操作时,如果发现分组后其他字段为空,通常是因为在分组操作中只保留了分组的字段和聚合结果(如 count、sum 等),而没有显式地保留其他字段。
要解决这个问题,可以通过以下方式在分组操作中保留其他字段的值:
方法 1:使用 $push 保留其他字段
在分组操作中,使用 $push 将其他字段的值保存到一个数组中。
示例代码
假设有一个 Order 集合,按 customerId 分组,并保留每个订单的 productName 和 amount 字段:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class OrderService {
@Autowired
private MongoTemplate mongoTemplate;
public List<CustomerOrders> groupByCustomerWithOrders() {
// 定义分组操作
GroupOperation groupOperation = Aggregation.group("customerId")
.push(new BasicDBObject("productName", "$productName")
.append("amount", "$amount"))
.as("orders");
// 定义聚合管道
Aggregation aggregation = Aggregation.newAggregation(
groupOperation
);
// 执行聚合操作
AggregationResults<CustomerOrders> results = mongoTemplate.aggregate(
aggregation, "orders", CustomerOrders.class
);
// 返回结果
return results.getMappedResults();
}
}
定义分组结果类
import java.util.List;
public class CustomerOrders {
private String customerId;
private List<OrderInfo> orders;
// 构造函数、getter 和 setter 省略
@Override
public String toString() {
return "CustomerOrders{customerId='" + customerId + "', orders=" + orders + "}";
}
}
class OrderInfo {
private String productName;
private double amount;
// 构造函数、getter 和 setter 省略
@Override
public String toString() {
return "OrderInfo{productName='" + productName + "', amount=" + amount + "}";
}
}
方法 2:使用 $first 或 $last 保留其他字段
如果只需要保留分组中某个字段的第一个或最后一个值,可以使用 $first 或 $last 操作符。
示例代码
按 customerId 分组,并保留每个分组的第一个 productName 和 amount 字段:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class OrderService {
@Autowired
private MongoTemplate mongoTemplate;
public List<CustomerFirstOrder> groupByCustomerWithFirstOrder() {
// 定义分组操作
GroupOperation groupOperation = Aggregation.group("customerId")
.first("productName").as("firstProductName")
.first("amount").as("firstAmount");
// 定义聚合管道
Aggregation aggregation = Aggregation.newAggregation(
groupOperation
);
// 执行聚合操作
AggregationResults<CustomerFirstOrder> results = mongoTemplate.aggregate(
aggregation, "orders", CustomerFirstOrder.class
);
// 返回结果
return results.getMappedResults();
}
}
定义分组结果类
public class CustomerFirstOrder {
private String customerId;
private String firstProductName;
private double firstAmount;
// 构造函数、getter 和 setter 省略
@Override
public String toString() {
return "CustomerFirstOrder{customerId='" + customerId + "', firstProductName='" + firstProductName + "', firstAmount=" + firstAmount + "}";
}
}
方法 3:使用 $addFields 保留其他字段
在分组操作后,可以使用 $addFields 将其他字段添加到分组结果中。
示例代码
按 customerId 分组,并保留每个分组的 productName 和 amount 字段:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import org.springframework.data.mongodb.core.aggregation.AddFieldsOperation;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class OrderService {
@Autowired
private MongoTemplate mongoTemplate;
public List<CustomerOrders> groupByCustomerWithOrders() {
// 定义分组操作
GroupOperation groupOperation = Aggregation.group("customerId")
.first("productName").as("firstProductName")
.first("amount").as("firstAmount");
// 添加其他字段
AddFieldsOperation addFieldsOperation = Aggregation.addFields()
.addField("productName").withValue("$firstProductName")
.addField("amount").withValue("$firstAmount")
.build();
// 定义聚合管道
Aggregation aggregation = Aggregation.newAggregation(
groupOperation,
addFieldsOperation
);
// 执行聚合操作
AggregationResults<CustomerOrders> results = mongoTemplate.aggregate(
aggregation, "orders", CustomerOrders.class
);
// 返回结果
return results.getMappedResults();
}
}
总结
| 方法 | 适用场景 | 特点 |
|---|---|---|
$push | 保留分组中所有文档的字段值 | 将字段值保存到数组中 |
$first | 保留分组中第一个文档的字段值 | 只保留第一个值 |
$last | 保留分组中最后一个文档的字段值 | 只保留最后一个值 |
$addFields | 在分组结果中添加其他字段 | 灵活添加字段 |
根据你的需求选择合适的方法,确保分组操作后其他字段的值能够正确保留。
1245

被折叠的 条评论
为什么被折叠?



