简体   繁体   English

在 Spring Data MongoDB 中返回流时指定游标选项?

[英]Specifying cursor options when returning a Stream in Spring Data MongoDB?

I'm using Spring Data MongoDB (spring-boot-starter-data-mongodb from Spring Boot 1.5.2.RELEASE ) and MongoDB 3.4.9 and have defined a repository defined that looks like this:我正在使用 Spring Data MongoDB(来自 Spring Boot 1.5.2.RELEASE spring-boot-starter-data-mongodb)和 MongoDB 3.4.9并定义了一个如下所示的存储库:

interface MyMongoDBRepository extends CrudRepository<MyDTO, String> {
    Stream<MyDTO> findAllByCategory(String category);
}

I then have a service, MyService that interacts with this repository:然后我有一个服务MyService与这个存储库交互:

@Service
class MyService {
    @Autowired
    MyMongoDBRepository repo;

    public void doStuff() {
        repo.findAllByCategory("category")
            .map(..)
            .filter(..)
            .forEach(..)
    }
}

There's quite a lot of data in the database and sometimes this error occur:数据库里面的数据比较多,有时候会出现这个错误:

2018-01-01 18:16:56.631 ERROR 1 --- [ask-scheduler-6] o.s.integration.handler.LoggingHandler : org.springframework.dao.DataAccessResourceFailureException: 
Query failed with error code -5 and error message 'Cursor 73973161000 not found on server <mongodb-server>' on server <mongodb-server>; 
nested exception is com.mongodb.MongoCursorNotFoundException: 
Query failed with error code -5 and error message 'Cursor 73973161000 not found on server <mongodb-server>' on server <mongodb-server> 
at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:77) 
at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:2135) 
at org.springframework.data.mongodb.core.MongoTemplate.access$1100(MongoTemplate.java:147) 
at org.springframework.data.mongodb.core.MongoTemplate$CloseableIterableCursorAdapter.hasNext(MongoTemplate.java:2506)
at java.util.Iterator.forEachRemaining(Iterator.java:115) 
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) 
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) 
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) 
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) 
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) 
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) 
at com.mycompany.MyService.doStuff(MyService.java:108) 
at com.mycompany.AnotherService.doStuff(AnotherService.java:42) 
at sun.reflect.GeneratedMethodAccessor2026.invoke(Unknown Source) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:498) 
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65) 
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) 
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81) 
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) 
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
at java.lang.Thread.run(Thread.java:748) Caused by: com.mongodb.MongoCursorNotFoundException: Query failed with error code -5 and error message 'Cursor 73973161000 not found on server <mongodb-server>' on server <mongodb-server> 
at com.mongodb.operation.QueryHelper.translateCommandException(QueryHelper.java:27) 
at com.mongodb.operation.QueryBatchCursor.getMore(QueryBatchCursor.java:213) 
at com.mongodb.operation.QueryBatchCursor.hasNext(QueryBatchCursor.java:103) 
at com.mongodb.MongoBatchCursorAdapter.hasNext(MongoBatchCursorAdapter.java:46) 
at com.mongodb.DBCursor.hasNext(DBCursor.java:145) 
at org.springframework.data.mongodb.core.MongoTemplate$CloseableIterableCursorAdapter.hasNext(MongoTemplate.java:2504) ... 24 more

I've read at various places that when using the vanilla MongoDB Java client you can configure the MongoDB cursor to either have no timeout or set a batch size to hopefully mitigate this.我在很多地方都读到过,在使用 vanilla MongoDB Java 客户端时,您可以将 MongoDB 游标配置为没有超时或设置批处理大小以希望减轻这种情况。

If this is the way to go, then how can I supply cursor options when returning a Stream from Spring Data MongoDB?如果这是要走的路,那么从 Spring Data MongoDB 返回Stream时如何提供游标选项?

Your error is occurring because you are processing the stream too slowly, so the cursor is timing out before you get to the next batch.您的错误发生是因为您处理流的速度太慢,因此光标在您进入下一批之前超时。

Batch size can be set on the Spring Data Query object , or on a Repository using the @Meta annotation.可以在Spring Data Query 对象或使用@Meta注释的 Repository 上设置批处理大小。 For example:例如:

Query query = query(where("firstname").is("luke"))
    .batchSize(100);

Or when using repositories:或者在使用存储库时:

@Meta(batchSize = 100)
List<Person> findByFirstname(String firstname);

See Spring Data MongoDB documentation for more details.有关更多详细信息,请参阅Spring Data MongoDB 文档

The cursor timeout can also be disabled on a per query basis using the same configuration.也可以使用相同的配置在每个查询的基础上禁用游标超时。 eg @Meta(flags = {CursorOption.NO_TIMEOUT}) .例如@Meta(flags = {CursorOption.NO_TIMEOUT})

The cursor timeout cannot be changed on a per-query basis.游标超时不能在每个查询的基础上更改。 That is a server configuration.那是服务器配置。 You need to use the cursorTimeoutMillis server parameter to change that server-wide.您需要使用cursorTimeoutMillis服务器参数来更改该服务器范围。

Regarding the two options you mentioned.关于你提到的两个选项。

  1. Batch size, You cannot set batch size using Repository class.批量大小,您不能使用 Repository 类设置批量大小。 You can do it using MongoTemplate .您可以使用MongoTemplateMongoTemplate Something like this像这样的东西

    final DBCursor cursor = mongoTemplate .getCollection(collectionName) .find(queryBuilder.get(), projection) .batchSize(readBatchSize); while (cursor.hasNext()) { ...... ...... }

But to use MongoTemplate you need to create a Custom Repository.但是要使用 MongoTemplate,您需要创建一个自定义存储库。

  1. Regarding Cursor timeout.关于光标超时。 You can do something like this你可以做这样的事情

    @Configuration public class MongoDbSettings { @Bean public MongoClientOptions setmongoOptions() { return MongoClientOptions.builder().socketTimeout(5000).build(); } }

There are many other options( heartbeat , connectiontimeout ) you can set for Mongo.您可以为 Mongo 设置许多其他选项( heartbeatconnectiontimeout )。 You can set those properties in your application.properties file, and then bind it using @Value in the above class and set(instead of hardcoding).您可以在 application.properties 文件中设置这些属性,然后在上面的类中使用@Value绑定它并设置(而不是硬编码)。
Unfortunately, spring-boot doesn't provide any way to specify these in application.properties file不幸的是,spring-boot 没有提供任何方式在application.properties文件中指定这些

You don't need to supply cursor options when returning a Stream from Spring Data MongoDB.从 Spring Data MongoDB 返回 Stream 时,您不需要提供游标选项。 The possible reason for this exception is how your service read data from Mongo.此异常的可能原因是您的服务如何从 Mongo 读取数据。 Possible reasons:可能的原因:

  1. You are sharing a single cursor across multiple threads您正在跨多个线程共享一个游标
  2. You are requested too many elements at once一次请求您的元素过多
  3. Load balancer before Mongo server Mongo 服务器之前的负载均衡器

See this Jira topic's comments for some ideas an direction applicable to your application.有关适用于您的应用程序的方向的一些想法,请参阅Jira 主题的评论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 响应式Spring Data Mongodb查询在不应该返回旧数据的情况下 - Reactive Spring Data Mongodb Query is returning old data when it should not 在Spring Data JPA存储库方法中返回Stream时出现UnsupportedOperationException - UnsupportedOperationException when returning Stream in Spring Data JPA repository method Spring data mongodb - &#39;cursor&#39; 选项是必需的 - Spring data mongodb - The 'cursor' option is required Spring Data MongoDb findById 不返回结果 - Spring Data MongoDb findById not returning results Spring Boot数据,MongoDB不返回结果 - Spring Boot data, MongoDB not returning results Spring Data MongoDB:如何在findAll方法中定义游标限制 - Spring data mongodb: How to define cursor limit in findAll method Spring集成:返回流 - Spring Integration: Returning stream 如何使用Spring data-mongodb-reactive从受限制的集合中流式传输 - How to stream from a capped collection with Spring data-mongodb-reactive 等待无功更改 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ 订阅激活 Spring 数据 MongoDB? - Wait for reactive change stream subscription to be active with Spring Data MongoDB? 在spring-data-mongodb中的$ last聚合中返回对象 - Returning object in $last aggregation in spring-data-mongodb
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM