MongoTemplate 进行分组操作后其他字段为空的解决方法

在使用 MongoTemplate 进行分组操作时,如果发现分组后其他字段为空,通常是因为在分组操作中只保留了分组的字段和聚合结果(如 countsum 等),而没有显式地保留其他字段。

要解决这个问题,可以通过以下方式在分组操作中保留其他字段的值:


方法 1:使用 $push 保留其他字段

在分组操作中,使用 $push 将其他字段的值保存到一个数组中。

示例代码

假设有一个 Order 集合,按 customerId 分组,并保留每个订单的 productNameamount 字段:

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 分组,并保留每个分组的第一个 productNameamount 字段:

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 分组,并保留每个分组的 productNameamount 字段:

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在分组结果中添加其他字段灵活添加字段

根据你的需求选择合适的方法,确保分组操作后其他字段的值能够正确保留。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰糖心书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值