[英]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.关于你提到的两个选项。
Batch size, You cannot set batch size using Repository class.批量大小,您不能使用 Repository 类设置批量大小。 You can do it using MongoTemplate
.您可以使用MongoTemplate
来MongoTemplate
。 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,您需要创建一个自定义存储库。
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 设置许多其他选项( heartbeat
、 connectiontimeout
)。 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:可能的原因:
See this Jira topic's comments for some ideas an direction applicable to your application.有关适用于您的应用程序的方向的一些想法,请参阅此Jira 主题的评论。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.