2011-02-06 42 views
1

我想在我的MongoDB数据库中使用Morphia遍历所有行(“文档”?)。偶尔我得到以下堆栈跟踪:Morphia/MongoDB:不能做getmore

com.mongodb.MongoInternalException: can't do getmore 
    at com.mongodb.DBApiLayer$Result._advance(DBApiLayer.java:378) 
    at com.mongodb.DBApiLayer$Result.hasNext(DBApiLayer.java:356) 
    at com.mongodb.DBCursor._hasNext(DBCursor.java:436) 
    at com.mongodb.DBCursor.hasNext(DBCursor.java:456) 
    at com.google.code.morphia.query.MorphiaIterator.hasNext(MorphiaIterator.java:40) 
    at 

在MongoDB的日志文件,我看到以下内容:

$ grep "cursorid not found" output.log 
Sun Feb 6 12:14:35 [conn13] getMore: cursorid not found App 2079575931792020691 
Sun Feb 6 12:44:17 [conn19] getMore: cursorid not found App 8364953818630631317 
Sun Feb 6 13:08:42 [conn20] getMore: cursorid not found App 7142256996888968009 

我对迭代代码是非常简单的:

for (App app : datastore.createQuery(App.class).fetch()) 
    { 
     log.info("app: " + app.getId()); 
     // do stuff with app 
    } 

吗啡错误? MongoDB的错误?我的错误?

更新:

我也在我的GlassFish日志中看到的是:

[#|2011-02-16T15:39:58.029+0000|WARNING|glassfish3.0.1|com.mongodb.TRACE|_ThreadID=28;_ThreadName=Thread-1;|The log message is null. 
java.lang.NullPointerException 
    at com.mongodb.DBApiLayer._cleanCursors(DBApiLayer.java:113) 
    at com.mongodb.DBApiLayer$DBCleanerThread.run(DBApiLayer.java:494) 
    at java.lang.Thread.run(Thread.java:662) 

回答

1

刚刚遇到同样的问题,而迭代通过一个非常大的查询。我发现这个吗啡的bug汇报了2011年3月21日:

http://code.google.com/p/morphia/issues/detail?id=251

问题251:启用/禁用超时做什么它说

相反的问题说,这将是1.0版固定。新的API disableCursorTimeout()暴露在1.00-SNAPHSHOT中。我正在运行long测试以查看它是否修复了此问题。

1

正如你可以看到在这个thread MongoDB的一定时间后释放光标。一种可能的解决方案可能是模拟批量迭代,并在循环中更新光标。

1

这是实际的代码吗?该代码似乎不太可能产生该异常。游标在闲置10分钟后超时。像这样的紧密循环似乎是不可能的。

您可以使用datastore.createQuery(App.class).disableTimeout()...来禁用Morphia中的游标超时。您也可以使用datastore.createQuery(App.class).fetchEmptyEntities(),如果你只是想@Id现场填写

而且,也没有必要显式调用fetch()如果你只是想用迭代器像一个for循环。当您想将迭代器存储在一个变量中并在多个位置使用它时,只需要获取fetch,而不是在单个for循环中。

+0

我试图在问我的问题时尽可能简化代码,所以你是正确的,我已经遗漏了可能有用的信息。 “做东西与应用程序”会发生什么:查询Web服务并将结果保存到磁盘上的文件。这通常以毫秒为单位执行,但我会在循环中添加一些时间检查,并查看是否没有导致超时的异常行为。谢谢。 –

+0

刚做了几轮测试,发现超时在迭代过程中进行了45分钟,这是可重复的。请注意,每次遍历我的迭代循环通常<1秒,所以它似乎是整个迭代过程的超时,而不是每次调用Iterator.next()之间的延迟。 –

+0

这不是那么简单。游标,迭代器从服务器批量获取数据;每个对next()的调用可能会或可能不会(批量大小可能为200+以上)必须与服务器通话。你有没有尝试disableTimeout选项? –