需求:使用mongoTemplate查询集合UserTrade数据,1.查询条件为assetNoList(字段assetNo集合)、idList(_id集合)及state=1。2.过滤重复数据,只按assetNo过滤,3.考虑assetNoList或idList有可能为空,4.增加需求,UserTrade集合有十几个很多字段,而我只需要返回_id、assetNo、userId、templateId、templateName、remarks、tradeNo这几个字段即可。5.对于重复数据行,point返回集合points,其他条件不变

// 1. 动态构建查询条件(处理空列表)
Criteria criteria = Criteria.where("state").is(Constant.DEL_FLAG_NORMAL);
if (idList != null && !idList.isEmpty() && !idList.stream().allMatch(Objects::isNull)) {
    criteria = criteria.and("_id").in(idList);
} else if (assetNoList != null && !assetNoList.isEmpty()) {
    criteria = criteria.and("assetNo").in(assetNoList);
}

// 2. 聚合框架实现去重和字段投影
Aggregation aggregation = Aggregation.newAggregation(
        Aggregation.match(criteria),
        Aggregation.group("assetNo")
                .first("_id").as("originalId")  // 保留原始_id
                .first("assetNo").as("assetNo")
                .first("userId").as("userId")
                .first("templateId").as("templateId")
                .first("templateName").as("templateName")
                .first("remarks").as("remarks")
                .first("tradeNo").as("tradeNo")
                .push("$point").as("points"),
        Aggregation.project("assetNo", "userId", "templateId", "templateName", "remarks", "tradeNo")
                .and("originalId").as("_id")  // 恢复原始_id
                .andInclude("points")  // 如果需要points
);

// 3. 执行聚合查询并映射结果
AggregationResultsresults = mongoTemplate.aggregate(aggregation,"userTrade",UserTrade.class);
Listlist = results.getMappedResults();
if(ListUtils.isEmpty(list)){
    continue;
}

UserTrade实体类

@Data

@Builder
public class UserTrade {

    /**
     * 主键id
     */
    private String _id;
    /**
     * 交易编号
     */
    @JsonSerialize(using = ToStringSerializer.class)
    private Long tradeNo;

    /**
     * 资产编号
     */
    private Long assetNo;
    /**
     * 员工用户id
     */
    private String userId;

    /**
     * 登录账号
     */
    private String username;

    /**
     * 手机号
     */
    private String phone;

    /**
     * 姓名
     */
    private String name;

    /**
     * 子模板id
     */
    private Long templateId;

    /**
     * 子模板名称
     */
    private String templateName;

    /**
     * 充值金额
     */
    private BigDecimal point;

    /**
     * 剩余金额
     */
    private BigDecimal surplusPoint;

    /**
     * 撤回状态(0-已撤回,1-未撤回)
     */
    private Integer state;

    private String stateName;
    /**
     * 过期时间
     */
    private Date expireTime;

    /**
     * 交易时间
     */
    private Date gmtCreate;

    /**
     * 交易备注
     */
    private String remarks;

    /**
     * 冻结状态
     */
    private Integer freezeState;

    /**
     * 冻结状态名称
     */
    private String freezeStateName;

    /**
     * 签名领取状态 0 未领取  1 已领取
     */
    private Integer collectState;

    private String collectStateValue;
    /**
     * 截止领取时间
     */
    private Date collectExpireTime;

    /**
     * 领取时间
     */
    private Date collectTime;

    /**
     * 分配编号(激活卡专有)
     */
    private String allotNumber;

    /**
     * 支出时间
     */
    private Date paidTime;

    /**
     * 激活卡卡号
     */
    private String assetAccount;

    /**
     * 结算类型
     */
    private Integer settType;

    /**
     * 结算类型 1.先结 2.后结
     */
    private String settTypeName;

    /**
     * 转入转出操作的
     * 原始批次编号(reTradeNo,转入记录则为从哪个批次转入的交易编号;
     * 转出记录则从自己的哪个批次转出的交易编号)
     */
    private String reTradeNo;

    /**
     * 目标/来源资产编号(reAssetNo,转入=从哪来,转出=到哪去)
     */
    private Long reAssetNo;

    /批量撤回特有字段*/

    private Listpoints;
}