【问题标题】:Provide limit on Spring Data Mongo repository对 Spring Data Mongo 存储库提供限制
【发布时间】:2018-10-24 18:29:08
【问题描述】:

使用最新的 Spring Data Mongo(撰写本文时为 2.1.1),如何指定获取“自定义”查询方法的第一条记录?这是一个例子:

@Query(value="{name: ?0, approval: {'$ne': null}}",
        sort="{'approval.approvedDate': -1}",
        fields = "{ _id: 1 }")
List<Item> getLatestApprovedIdByName(String name, Pageable pageable);

/**
 * Finds the id of the most recently approved document with the given name.
 */
default Item getLatestApprovedIdByName(String name) {
    return getLatestApprovedIdByName(name, PageRequest.of(0, 1)).stream().findFirst().orElse(null);
}

理想情况下,我可以只使用 String 参数来注释 getLatestApprvedIdByName。 org.springframework.data.mongodb.repository.Query 注释上似乎没有限制字段。这似乎很奇怪,因为我可以模拟命名方法所做的所有事情,除了“findFirst”。如果没有 Pageable,我会得到 IncorrectResultSizeDataAccessException,并且返回 List 是不可接受的,因为我不想浪费时间返回任意大的结果,以及需要处理 0 或 1 项可能性的复杂代码。

【问题讨论】:

  • 几个问题。您的查询是否返回超过 1 个项目?什么时候抛出IncorrectResultSizeDataAccessException?当你指定方法为List&lt;Item&gt; getLatestApprovedIdByName(String name);?
  • 是的,有很多文档与查询匹配。我想要最新批准的。如果我可以创建一个像 findFirstByNameOrderByApprovedDateDesc 这样的方法,它会做我想要的,除了查询和排序太复杂而无法放入方法名称,正如您在我的示例中看到的那样,因为我正在查看嵌套字段。

标签: java mongodb spring-data spring-data-mongodb


【解决方案1】:

由于您的查询返回多个文档,因此无法使其直接返回单个 Item

使用Stream

// Repository
@Query(value="{name: ?0, approval: {'$ne': null}}",
        sort="{'approval.approvedDate': -1}",
        fields = "{ _id: 1 }")
Stream<Item> getLatestApprovedIdByName(String name);

// Service
default Item getLatestApprovedIdByName(String name) {
    return getLatestApprovedIdByName(name).stream().findFirst().orElse(null);
}

由于Stream 的工作方式,您将只获取第一个查询结果而不是整个结果集。更多信息请查看documentation

使用PagePageable

// Repository
@Query(value = "{name: ?0, approval: {'$ne': null}}", fields = "{ _id: 1 }")
Page<Item> getLatestApprovedIdByName(String name, Pageable pageable);

// Service
default Item getLatestApprovedIdByName(String name) {
    PageRequest request = new PageRequest(0, 1, new Sort(Sort.Direction.DESC, "approval.approvedDate"));
    return getLatestApprovedIdByName(name, request).getContent().get(0);
}

通过使用PageRequest,您可以指定需要多少个结果以及指定排序顺序。基于this answer

【讨论】:

  • 我试过 Stream 但我认为它不起作用。我会再试一次。我以为我在文档中看到了它,想知道它是否真的只会拉第一个项目,或者它是否会拉一些项目窗口(项目文档非常大,我还有其他方法)。我明天试试这个。但这是很多代码,在这一点上,使用 MongoTemplate 并跳过 spring 数据存储库似乎更容易!我当然花了更多时间来获得在基于 MongoTemplate 的 DAO 上工作的“简单”方式。
  • 我试过了,它在功能上确实有效,但在性能上却没有。在我从 List 更改为 Stream(并且我保留了 Pageable)之后,直接代理该方法的 REST 端点的响应时间从 8 毫秒变为 4.7 秒(我测试了多次和服务器)。这很奇怪,因为即使查询中取消了限制,_id 字段的生成也只保留了下来,并且测试数据库在集合中只有几个文档。所以,我将继续使用 List 方法。听起来答案是您不能仅通过 @Query 注释进行限制,我可以将其标记为已回答。
  • 我想知道流和页面哪个更快。我希望将来@Query 支持限制。目前最高效的方式是使用 query.limit() 编写查询
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 2016-03-06
  • 2015-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多