为什么ArangoDB(使用Python-Arango)return ERR 1600 ERROR_CURSOR_NOT_FOUND?

Why does ArangoDB (using Python-Arango) return ERR 1600 ERROR_CURSOR_NOT_FOUND?

问题

我遍历整个顶点集合,例如journals,并用它来创建边,author,从 person 到给定的 journal

我使用 python-arango,代码类似于:

for journal in journals.all():
    create_author_edge(journal)

我有一个相对较小的数据集,journals-collection 只有大约。 1300 份文件。但是:这 超过 1000,这是 Web 界面中的批处理大小 - 但我不知道这是否相关。

问题是它引发了一个 CursorNextError, and returns HTTP 404 and ERR 1600 from the database, which is the ERROR_CURSOR_NOT_FOUND error:

Will be raised when a cursor is requested via its id but a cursor with that id cannot be found.

对原因的见解

ArangoDB Cursor Timeout, and from this issue,我怀疑这是因为光标的 TTL 在数据库中已过期,并且在 python 堆栈跟踪中看到类似这样的内容:

# Part of the stacktrace in the error:
(...)
if not cursor.has_more():
    raise StopIteration
cursor.fetch()  <---- error raised here
(...)

如果我快速遍历整个集合,即如果我这样做 print(len(journals.all()) 它输出“1361”没有错误。

当我用 AQL 替换 journals.all() 并增加 TTL 参数时,它可以正常工作:

for journal in db.aql.execute("FOR j IN journals RETURN j", ttl=3600):
    create_author_edge(journal)

但是,如果没有 ttl 参数,AQL 方法会给出与使用 journals.all().

相同的错误

更多信息

最后一条信息是,当出现错误时,我正在 运行 我的个人笔记本电脑上。在我的工作计算机上,使用相同的代码创建图表并用相同的数据填充它,但没有出现任何错误。因为我在度假,所以我无法访问我的工作计算机来比较版本,但是两个系统都是在夏天安装的,所以版本很可能是相同的。

问题

我不知道这是 python-arango 还是 ArangoDB 的问题。我相信因为当 TTL 增加时没有问题,它可能表明 ArangodDB 有问题而不是 Python 驱动程序,但我不知道。

(我添加了一个功能请求以将 ttl-param 添加到 .all()-方法 here。)

对发生这种情况的原因有何见解?


我没有创建标签的代表"python-arango",所以如果有人能创建它并标记我的问题就太好了。

在服务器内部,简单查询将被翻译成 all()。 正如在引用的 github 问题上所讨论的,简单查询不支持 TTL 参数,并且不会获取它们。

此处首选的解决方案是在客户端使用 AQL-Query,这样您就可以指定 TTL 参数。

一般来说,您应该避免一次从数据库中提取所有文档,因为这可能会引入其他缩放问题。您应该使用适当的 AQL 和索引支持的 FILTER 语句(使用 explain() 重新验证)来获取您需要的文档。

如果需要遍历数据库中的所有文档,请使用分页。这通常是通过将范围 FILTERLIMIT 子句组合来实现的最佳方式:

FOR x IN docs
  FILTER x.offsetteableAttribute > @lastDocumentWithThisID
  LIMIT 200
    RETURN x

这就是我的做法。您可以指定 more args 参数,这很容易做到。

查看源代码,您可以看到文档字符串说明了要做什么

def AQLQuery(self, query, batchSize = 100, rawResults = False, bindVars = None, options = None, count = False, fullCount = False,
             json_encoder = None, **moreArgs):
    """Set rawResults = True if you want the query to return dictionnaries instead of Document objects.
    You can use **moreArgs to pass more arguments supported by the api, such as ttl=60 (time to live)"""
from pyArango.connection import *
conn = Connection(username=usr, password=pwd,arangoURL=url)# set this how ya need
db = conn['collectionName']#set this to the name of your collection
aql = """ for journal in journals.all():
    create_author_edge(journal)"""
doc = db.AQLQuery(aql,ttl=300)


这就是你需要做的!