如何在 MongoDB 中高效查询并获取文档 ID 列表

本文介绍在 spring data mongodb 中通过 `@query` 注解精准投影 `_id` 字段,以轻量方式批量获取文档 id 列表,避免加载冗余字段,提升查询性能。

在实际开发中,经常需要仅获取集合中所有文档的 _id(例如用于批量处理、缓存预热或前端分页标识),而非完整实体对象。MongoDB 原生支持字段投影(projection),Spring Data MongoDB 也提供了简洁的集成方式。

✅ 正确做法:使用 @Query + 字段投影

在 MongoRepository 接口中,定义如下方法:

@Repository
public interface UserRepository extends MongoRepository {
    @Query(value = "{}", fields = "{_id: 1}")
    List findIds();
}
  • value = "{}" 表示匹配全部文档(等价于无条件查询);
  • fields = "{_id: 1}" 表示仅返回 _id 字段(1 表示包含,0 表示排除;注意:除 _id 外其他字段默认被排除);
  • 返回类型为 List,Spring 会自动将 _id 映射到实体类的 id 字段(需确保 User 类中 id 字段已正确标注 @Id)。

若你希望直接返回 List(更符合业务语义),推荐搭配 @Aggregation 或自定义 DTO;但最简方案是后处理提取:

List userIds = userRepository.findIds().stream()
    .map(User::getId)
    .collect(Collectors.toList());

⚠️ 注意事项

  • 不要省略 fields 参数——若只写 @Query("{}"),MongoDB 将返回完整文档,造成不必要的网络与内存开销;
  • _id 在 MongoDB 中默认是 ObjectId 类型,若 Java 实体中 id 字段声明为 String,Spring 会自动完成 ObjectId ↔ String 转换(前提是 MongoCo

    nfiguration 已启用默认转换器);
  • 如需去重或添加条件(如按 color 筛选),可扩展 value 参数:
    @Query(value = "{color: 'blue'}", fields = "{_id: 1}")
    List findBlueUserIds();

✅ 替代方案(进阶)

对于纯 ID 列表需求,也可使用聚合管道实现零实体映射:

@Aggregation(pipeline = {
    "{ $project: { _id: { $toString: '$_id' } } }",
    "{ $group: { _id: null, ids: { $push: '$_id' } } }",
    "{ $project: { _id: 0, ids: 1 } }"
})
List>> aggregateIds();

但该方式复杂度高,日常推荐优先使用字段投影 + List 的简洁模式。

总之,合理利用 fields 投影是 MongoDB 查询优化的关键实践之一——小改动,大收益。