
本文介绍在 spring data mongodb 中通过 `@query` 注解仅查询 `_id` 字段,避免加载冗余数据,从而高效获取用户 id 列表的方法,并提供完整实现与最佳实践。
在实际开发中,经常需要批量获取集合中所有文档的 _id(例如用于分页预加载、缓存键生成或关联查询准备),但不希望加载整个文档对象——这不仅浪费网络带宽,还会增加内存开销和序列化成本。MongoDB 原生支持 投影(Projection) 机制,可精确控制返回字段;Spring Data MongoDB 通过 @Query 的 fields 参数完美封装了该能力。
✅ 正确用法:使用字段投影只返回 _id
假设你已定义了 User 实体类及对应的 MongoRepository:
public class User {
@Id
private String id;
private String shape;
private String color;
// getters & setters...
}
public interface UserRepository extends MongoRepository {
@Query(value = "{}", fields = "{_id: 1}")
List findIds();
} ? 说明: value = "{}" 表示空查询条件(即匹配全部文档); fields = "{_id: 1}" 是 MongoDB 投影语法,表示仅包含 _id 字段(其他字段自动排除); 返回类型为 List 是安全的,因为 Spring Data 会将 _id 自动映射到 User.id 字段,其余属性保持 null。
✅ 进阶推荐:直接返回 String ID 列表(更简洁)
若你仅需 ID 字符串(如 Set
public interface UserIdProjection {
String getId(); // 注意:方法名需与 _id 映射字段一致(默认@Id字段)
}
public interface UserRepository extends MongoRepository {
@Query(value = "{}", fields = "{_id: 1}")
List findIdProjections();
// 或使用派生查询(无需注解)
List findAllBy();
} 调用后即可直接提取 ID:
Listprojections = userRepository.findIdProjections(); List ids = projections.stream() .map(UserIdProjection::getId) .collect(Collectors.toList());
⚠️ 注意事项
- ❌ 避免使用 fields = "{id: 1}"(错误字段名):MongoDB 中主键字段名为 _id,Java 实体中虽用 @Id 标注 id 属性,但投影必须写 _id;
- ✅ 若实体中 @Id 字段类型为 ObjectId,确保 fields="{_id: 1}" 返回的仍是字符串格式(Spring Data 默认将 ObjectId 序列化为十六进制字符串);
- ? 生产环境建议添加索引:db.user.createIndex({"_id": 1})(_id 默认已有唯一索引,无需额外操作);
- ? 对于超大数据集,考虑使用 find().projection() 配合 Stream 或分页游标(如 skip/limit 或 find().cursor())防止 OOM。
通过合理利用投影查询,你能在毫秒级响应内获取数万 ID,同时显著降低服务端资源消耗——这是构建高性能 MongoDB 应用的关键实践之一。










