Spring + MongoDB-MongoTemplate +条件查询

时间:2019-03-06 08:46:20

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

我正在使用Spring Boot + MongoDB。我需要根据一些条件来查询数据库,其中我的方法如下所示:

insert into table(a,b,c,d,e,f) values ('Rumania',N'Sighișoara',GETDATE(),0,0,'Test')

我面临的问题是: 在

search.addCriteria(Criteria.where(“ ItmId”)。in(request.getItmIds()));

request.getItmIds有100万个ID,由于这个原因,我遇到了异常

org.bson.BsonMaximumSizeExceededException:文档大小46282052大于最大值16793600

有人可以帮我吗?

2 个答案:

答案 0 :(得分:0)

如果您使用的是MongoTemplate,则应该能够像这样分页数据:

Query search = new Query()
    .with(PageRequest.of(0, 100)) 
    .addCriteria(Criteria.where("ItmId").in(request.getItmIds()));

但是,请注意,MongoTemplate无法返回Page<MyCollection>,从而无法为您提供有关总共有多少项的更多信息。

要解决此问题,您必须手动执行计数查询。您可以将其与PageableExecutionutils结合使用,如this answer所示。

现在您可以分页数据,并且知道元素的总数,那么您应该可以编写一个循环以获取所有数据。

请注意:您仍然在每个查询中发送那100万个ID,MongoDB试图为此类复杂查询找到结果可能会遇到一些困难/性能问题。


或者,在这种情况下,您可以将request.getItmIds()切成较小的列表,然后分别执行。 Apache Commons Collections 4有一个ListUtils.partition()方法可以帮助您:

ListUtils
    .partition(request.getItmIds(), 100)
    .stream()
    .map(ids -> Criteria.where("ItmId").in(ids))
    .map(criteria -> new Query().addCriteria(criteria))
    .map(query -> mongoTemplate.find(query, MyCollection.class))
    .flatMap(Collection::stream)
    .collect(Collectors.toList());

这会将request.getItmIds()分成多个列表,每个列表共有100个ID。之后,它将对这些ID执行单独的查询,然后将这些列表连接到一个大列表中。


请注意,但是,无论采用何种方式实现,执行速度都可能很慢。即使您正在执行较小的查询,您仍在尝试获取100万个文档,具体取决于您在何处使用它,可能会遇到其他各种问题,例如:

  • 由于试图在内存中加载一百万个对象而导致的内存问题
  • 如果由于某处的REST API而提供带宽问题,则为带宽问题

根据您打算如何使用它,您可能必须提出不同的解决方案,例如:

  • 使用批处理
  • 将分页应用于源(生成这100万个ID的源)
  • 流式传输这些结果,而不是尝试生成包含所有对象的列表

答案 1 :(得分:-1)

如果您使用的是Spring Data JPA,则可以执行以下操作: findBySomeField(String someField)

如果您有更复杂的查询,则可以实际使用JPQL并编写自定义查询。

@Query(value = "SELECT o.* from SomeObject o WHERE :someField IS NULL OR o.someField = :somefield)
public findBySomeField(@Param("someField") String someField);