You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data Mongo聚合中同时使用$trim与$toLower操作的问题排查

解决Spring Data MongoDB聚合中嵌套$trim和$toLower的问题

首先得指出两个关键问题:你的原始MongoDB聚合查询存在语法错误,以及Spring Data MongoDB中嵌套字符串操作的正确写法。

第一步:修正原始MongoDB聚合查询

你的原查询里$group阶段的语法有问题:count字段应该放在$group的对象内部,而且非_id字段必须使用累加器(比如$first、$last),否则MongoDB会报错。修正后的正确查询如下:

db.qabr.aggregate([ 
  { $match: { name: { "$ne": "" } }}, 
  { 
    $group: { 
      _id: { name: { $trim: { input: { $toLower: "$name" } } } }, 
      qabrNumber: { $first: "$qabrNumber" }, // 用$first获取分组内第一个值,根据需求也可以用$push等
      qabristaan: { $first: "$qabristaan" },
      count: { "$sum": 1 } 
    } 
  }, 
  { $match: { count: { "$gt": 1 } } } 
])

第二步:Spring Data MongoDB的正确实现

你之前的代码报错是因为StringOperators.Trim.valueOf()方法无法正确处理嵌套的ToLower操作符。下面提供两种可行的解决方案:

方案1:手动构建AggregationExpression(兼容大多数版本)

直接手动构造嵌套的MongoDB表达式,避免依赖操作符的链式调用可能出现的问题:

import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationExpression;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import org.springframework.data.mongodb.core.aggregation.MatchOperation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.bson.Document;

// 1. 匹配非空name的文档
MatchOperation matchNonEmptyName = Aggregation.match(Criteria.where("name").ne(""));

// 2. 分组阶段:手动构造_id的标准化name(先转小写再去空格)
GroupOperation groupByNormalizedName = Aggregation.group(
        AggregationExpression.from(context -> 
                new Document("name", 
                        new Document("$trim", 
                                new Document("input", 
                                        new Document("$toLower", "$name")
                                )
                        )
                )
        )
)
.first("qabrNumber").as("qabrNumber")
.first("qabristaan").as("qabristaan")
.count().as("count");

// 3. 筛选出重复项(计数>1)
MatchOperation matchDuplicates = Aggregation.match(Criteria.where("count").gt(1));

// 组装并执行聚合
Aggregation aggregation = Aggregation.newAggregation(
        matchNonEmptyName,
        groupByNormalizedName,
        matchDuplicates
);

// 替换成你的实体类
AggregationResults<YourQabrEntity> results = mongoTemplate.aggregate(aggregation, "qabr", YourQabrEntity.class);

方案2:使用StringOperators的链式调用(适用于Spring Data MongoDB 3.x+)

如果你的Spring Data MongoDB版本足够新,可以通过trim()方法直接传入toLower()的结果,先新增一个标准化字段再分组,代码更直观:

import org.springframework.data.mongodb.core.aggregation.AddFieldsOperation;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import org.springframework.data.mongodb.core.aggregation.MatchOperation;
import org.springframework.data.mongodb.core.aggregation.StringOperators;
import org.springframework.data.mongodb.core.query.Criteria;

// 1. 匹配非空name
MatchOperation matchNonEmptyName = Aggregation.match(Criteria.where("name").ne(""));

// 2. 新增一个标准化后的name字段:先转小写再去首尾空格
AddFieldsOperation normalizeName = Aggregation.addFields()
        .addField("normalizedName")
        .withValue(StringOperators.Trim.trim(StringOperators.ToLower.toLower("name")))
        .build();

// 3. 按标准化后的name分组
GroupOperation groupByNormalizedName = Aggregation.group("normalizedName")
        .first("qabrNumber").as("qabrNumber")
        .first("qabristaan").as("qabristaan")
        .count().as("count");

// 4. 筛选重复项
MatchOperation matchDuplicates = Aggregation.match(Criteria.where("count").gt(1));

// 组装聚合
Aggregation aggregation = Aggregation.newAggregation(
        matchNonEmptyName,
        normalizeName,
        groupByNormalizedName,
        matchDuplicates
);

// 执行查询
AggregationResults<YourQabrEntity> results = mongoTemplate.aggregate(aggregation, "qabr", YourQabrEntity.class);

为什么你的原始Spring代码报错?

你之前用StringOperators.Trim.valueOf(StringOperators.ToLower.lowerValueOf("name")),是因为valueOf()方法默认接收的是字段名或简单表达式,无法正确解析嵌套的ToLower操作符,导致生成的MongoDB表达式不符合预期,最终抛出Unrecognized expression '$trim'错误。改用上面的两种方式就能解决这个问题。

内容的提问来源于stack exchange,提问作者aorticDefiance

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 16:22:35