Spring Boot如何实现从MongoDB集合中随机返回单个category为escortedTours的文档?
实现每次刷新返回单个随机的escortedTours文档方案
我来帮你搞定这个问题!要实现每次刷新页面返回单个随机的escortedTours分类文档,我们可以分两种场景调整代码,你可以根据业务数据量选择:
方案一:内存中随机选取(适合数据量较小的场景)
这种方法不用修改Repo层,只需要调整Service和Controller的逻辑,简单易上手:
- 修改ServiceImpl层:
把方法的返回类型从List<PackageHoliday>改成单个PackageHoliday,获取所有符合条件的文档后,生成随机索引挑出一个。记得处理空列表的情况,避免空指针:
@Override public PackageHoliday findRandomEscortedTour() { List<PackageHoliday> escortedTours = packageHolidayRepository.findByTypeOfPackageHoliday("escortedTours"); if (escortedTours.isEmpty()) { return null; // 也可以抛出自定义业务异常,根据你的需求处理 } // 生成0到列表长度-1之间的随机索引 Random random = new Random(); int randomIndex = random.nextInt(escortedTours.size()); return escortedTours.get(randomIndex); }
- 修改Controller层:
同步修改接口的返回类型,并调用新的Service方法:
@GetMapping("/getEscortedTours") public PackageHoliday getRandomEscortedTour() { return packageHolidayService.findRandomEscortedTour(); }
方案二:MongoDB原生随机查询(适合数据量大的场景)
如果escortedTours分类下的文档数量很多,方案一先查所有再随机会占用较多内存。这时候可以用MongoDB的$sample聚合操作符,让数据库直接返回随机文档,性能更优:
- 修改Repo层:
新增自定义查询方法,借助MongoTemplate实现聚合查询:
// 先定义自定义Repo接口 public interface PackageHolidayCustomRepository { PackageHoliday findRandomEscortedTour(); } // 实现自定义Repo逻辑 @Repository public class PackageHolidayRepositoryImpl implements PackageHolidayCustomRepository { private final MongoTemplate mongoTemplate; // 构造注入MongoTemplate public PackageHolidayRepositoryImpl(MongoTemplate mongoTemplate) { this.mongoTemplate = mongoTemplate; } @Override public PackageHoliday findRandomEscortedTour() { Aggregation aggregation = Aggregation.newAggregation( // 先筛选出escortedTours分类的文档 Aggregation.match(Criteria.where("typeOfPackageHoliday").is("escortedTours")), // 随机取1个文档 Aggregation.sample(1) ); AggregationResults<PackageHoliday> results = mongoTemplate.aggregate(aggregation, "packageHoliday", PackageHoliday.class); return results.getUniqueMappedResult(); } } // 让你的主Repo接口继承自定义接口 public interface PackageHolidayRepository extends MongoRepository<PackageHoliday, String>, PackageHolidayCustomRepository { List<PackageHoliday> findByTypeOfPackageHoliday(String typeOfPackageHoliday); }
- 修改ServiceImpl层:
调用新的Repo方法:
@Override public PackageHoliday findRandomEscortedTour() { return packageHolidayRepository.findRandomEscortedTour(); }
- 修改Controller层:
和方案一一致,返回单个PackageHoliday对象:
@GetMapping("/getEscortedTours") public PackageHoliday getRandomEscortedTour() { return packageHolidayService.findRandomEscortedTour(); }
两种方案各有优劣:方案一简单易实现,适合数据量小的场景;方案二直接在数据库层面处理,避免大量数据加载到内存,性能更好,适合数据量大的场景。你可以根据实际情况选择~
内容的提问来源于stack exchange,提问作者devnoob
相关产品推荐
相关产品推荐

