spring - Spring Data mongoDB:如何根据日期为每个名称获取一个文档
问题描述
我有一个要执行的 mongoDB 请求,最初对我来说听起来很容易,但让我汗流浃背,结果我不太相信。我搜索了很多类似的问题,但没有一个真正满足我的需求。我正在为我的后端使用 Spring Boot 框架。目标相当简单。我在数据库中有一组文档,如下例所示:
[{“name” : “Bob”,
“contract” : false,
”ranking” : 3,
“timestamp”: 1606867200},
{“name” : “Bob”,
“contract” : true,
”ranking” : 5,
“timestamp”: 1606953600},
{“name” : “Roger”,
“contract” : true,
”ranking” : 25,
“timestamp”: 1607040000},
{“name” : “Bob”,
“contract” : true,
”ranking” : 5,
“timestamp”: 1607040000}]
我想为每个唯一名称获取一个文档,其中时间戳(即以纪元毫秒格式表示的日期)最高(即最新日期)。所以在上面的例子中我会有两个结果:
[{“name” : “Roger”,
“contract” : true,
”ranking” : 25,
“timestamp”: 1607040000},
{“name” : “Bob”,
“contract” : true,
”ranking” : 5,
“timestamp”: 1607040000}]
为此,我找到的唯一解决方案是使用聚合。这可以在 Spring 中使用 mongoTemplate 或在我的情况下使用聚合存储库方法来完成,该方法工作正常,也请参见此处了解详细信息
我想要的是在 mongo 中为每个名称获取一个文档,为每个名称选择的文档是具有最大时间戳的文档。据我了解,这不是直接可行的。我们必须使用聚合管道创建一个新文档,告诉他根据名称进行分组_id: '$name'
并选择最高时间戳:timestamp: {$max: '$timestamp'}
。但是,这样做会创建一个只有两个字段的文档:_ID 和时间戳,我在 Spring 中的 POJO 需要(名称、合同、排名、时间戳)。我发现添加其余字段的唯一方法是这样做:
String myAggregation = "{ $group: {" +
"_id: '$name'," +
"name: {$first: '$name'}," +
"contract: {$first: '$contract'}," +
"ranking: {$first: '$ranking'}," +
"timestamp: {$max: '$timestamp'}," +
"}}";
// find the latest scan status for each individual UID
@Aggregation(myAggregation)
List<HotlistStatusEntity> findLastStatusOfEachName();
但我觉得在某些情况下,这可能会导致不希望的结果,因为 $first 从文档中选择的值与 $max 选择的值不同。我缺乏一种清晰的方式来解释我的担忧,但在做我所做的事情时,我不会获取现有文档的列表,而是通过选择“这里和那里”的值来重新创建文档。尽管我的测试从未导致意外结果,但我仍然对此没有信心。那么是否有更安全或更清洁的方式来实现这一目标?在此先感谢您的帮助。
解决方案
推荐阅读
- python - 如何使用 Matplotlib 的 .plot(table = True) 移动表格位置
- reactjs - Webstorm 中的 ESLint 无法识别 React 类型
- flutter - Dart/Flutter 的代码覆盖率可视化(特别适用于 Windows 和 VS Code)
- vue.js - 当某些环境变量未设置时,有没有办法强制 `vue-cli-service build` 失败?
- leaflet - 使用 Leaflet 寻找可用于历史不同时刻的地图图块
- html - 如何使用 vh 和 vw 修复响应式网页的高度
- android - BottomSheetBehavior 泄漏片段?
- python - 是否可以使用 MDI 获得局部特征重要性或使用 RF 或 ET 获得置换重要性?
- go - 请求正文始终为空
- python - TypeError: unhashable type: 'list' 用于文本摘要