pymongo.errors.CursorNotFound:游标id'...'在服务器上无效

sna*_*ken 51 python mongodb pymongo

我试图使用以下代码获取mongo数据库中存在的一些ID:

client = MongoClient('xx.xx.xx.xx', xxx)
db = client.test_database
db = client['...']
collection = db.test_collection
collection = db["..."]


for cursor in collection.find({ "$and" : [{ "followers" : { "$gt" : 2000 } }, { "followers" : { "$lt" : 3000 } }, { "list_followers" : { "$exists" : False } }] }): 
    print cursor['screenname']
    print cursor['_id']['uid']
    id = cursor['_id']['uid']
Run Code Online (Sandbox Code Playgroud)

但是,过了一会儿,我收到这个错误:

pymongo.errors.CursorNotFound:游标id'...'在服务器上无效.

我发现这篇文章提到了这个问题.然而,我不清楚采取哪种解决方案.可以使用find().batch_size(30)吗?上面的命令到底是做什么的?我可以使用所有数据库ID batch_size吗?

Chr*_*n P 79

您收到此错误是因为光标在服务器上超时(10分钟不活动后).

从pymongo文档:

如果MongoDB中的游标已经打开了很长时间而没有对它们执行任何操作,则它们可以在服务器上超时.这可能导致在尝试迭代游标时引发CursorNotFound异常.

当您调用该collection.find方法时,它会查询一个集合并将光标返回给文档.要获取文档,请迭代光标.迭代游标时,驱动程序实际上是向MongoDB服务器发出请求以从服务器获取更多数据.每个请求中返回的数据量由batch_size()方法设置.

文档:

限制一批中返回的文档数量.每批需要往返服务器.可以对其进行调整以优化性能并限制数据传输.

将batch_size设置为较低的值将帮助您解决超时错误错误,但它会增加您访问MongoDB服务器以获取所有文档的次数.

默认批量大小:

对于大多数查询,第一批返回101个文档或只有足够的文档超过1兆字节.批量大小不会超过最大BSON文档大小(16 MB).

没有通用的"正确"批量大小.您应该使用不同的值进行测试,看看您的用例的适当值是什么,即您可以在10分钟的窗口中处理多少文档.

最后的手段将是你设置的no_cursor_timeout=True.但是,在完成数据处理后,您需要确保光标已关闭.

  • 我将 batch_size 定义为 50。但是我得到了同样的错误 pymongo.errors.CursorNotFound: cursor id '' not valid at server。我必须设置 batch_size 的正确值是多少? (2认同)

Man*_*ani 45

使用no_cursor_timeout=True这样:

cursor=db.images.find({}, {'id':1, 'image_path':1, '_id':0}, no_cursor_timeout=True)
for i in cursor:
    # .....
    # .....
cursor.close() # use this or cursor keeps waiting so ur resources are used up
Run Code Online (Sandbox Code Playgroud)

  • 使用“no_cursor_timeout=True”后游标仍然崩溃。有什么理由吗?我必须同时使用“no_cursor_timeout”和“batch_size”吗?我收藏了大约 3000 万张唱片。 (2认同)

HIS*_*ISI 7

您使用光标的时间超过了超时时间(大约 10 分钟),因此光标不再存在。

您应该选择一个较低的 batch_size 值来解决此问题:

(以 Pymongo 为例)

col.find({}).batch_size(10)
Run Code Online (Sandbox Code Playgroud)

或者

将超时设置为 false col.find(timeout=False),最后不要忘记关闭游标。


Mai*_*ret 6

这是一个超时问题,mongodb默认是10分钟。我更喜欢通过登录 mongo 并运行管理查询更新来解决此问题:

use admin 
db.runCommand({setParameter:1, cursorTimeoutMillis: 1800000})
Run Code Online (Sandbox Code Playgroud)

其中 1800000 相当于 30 分钟,对于我的用例来说足够了。

或在终端(10800000==3h):

use admin 
db.runCommand({setParameter:1, cursorTimeoutMillis: 1800000})
Run Code Online (Sandbox Code Playgroud)