Morphia / MongoDB:做得不够好

时间:2011-02-06 18:36:35

标签: java mongodb morphia

我正在尝试使用Morphia迭代MongoDB数据库中的所有行(“文档”?)。偶尔我会得到以下stacktrace:

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
    }

Morphia bug? 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)

3 个答案:

答案 0 :(得分:1)

正如您在thread中看到的那样,MongoDB会在一段时间后发布游标。一种可能的解决方案可能是模拟批量迭代并在周期和周期更新光标。

答案 1 :(得分:1)

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

您可以使用datastore.createQuery(App.class).disableTimeout()...禁用Morphia中的光标超时。如果您只想填写datastore.createQuery(App.class).fetchEmptyEntities()字段,也可以使用@Id

此外,如果您只想在for循环中使用迭代器,则无需显式调用fetch();如果要将迭代器存储在变量中并在多个位置使用它,而不是在单个for循环中使用,则只需要获取。

答案 2 :(得分:1)

在迭代一个非常大的Query时遇到了同样的问题。我在2011年3月21日发现了这个Morphia bug:

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

  

问题251:启用/禁用超时与它所说的相反

该问题表明它将在1.0版中修复。新API disableCursorTimeout()在1.00-SNAPHSHOT中公开。我正在运行 long 测试以确定它是否解决了问题。