ArangoDB:通过示例插入查询功能

Nat*_*ner 6 query-optimization graph-databases arangodb aql

我的部分图表是使用两个大型集合之间的巨型连接构建的,每次我将文档添加到任一集合时都会运行它.该查询基于较旧的帖子.

FOR fromItem IN fromCollection
    FOR toItem IN toCollection
        FILTER fromItem.fromAttributeValue == toItem.toAttributeValue
        INSERT { _from: fromItem._id, _to: toItem._id, otherAttributes: {}} INTO edgeCollection
Run Code Online (Sandbox Code Playgroud)

这需要大约55,000秒才能完成我的数据集.我绝对欢迎提出更快的建议.

但我有两个相关的问题:

  1. 我需要一个upsert.通常,upsert没关系,但在这种情况下,因为我无法预先知道密钥,所以对我没有帮助.为了获得前面的密钥,我需要通过示例查询以找到其他相同的现有边的密钥.这似乎是合理的,只要它不会破坏我的性能,但我不知道如何在AQL中有条件地构造我的查询,以便在等效边缘尚不存在的情况下插入边缘,但如果等效边缘则不执行任何操作确实存在.我怎样才能做到这一点?
  2. 每次将数据添加到任一集合时,我都需要运行它.我需要一种方法只在最新的数据上运行它,这样它就不会尝试加入整个集合.如何编写允许我只加入新插入记录的AQL?它们与Arangoimp一起添加,我无法保证它们的更新顺序,因此我无法在创建节点的同时创建边缘.我如何只加入新数据?每次添加记录时我都不想花费55k秒.

Max*_*fer 8

如果您在没有任何索引的情况下运行查询,则必须执行两次嵌套的完整集合扫描,这可以通过查看输出来看出

db._explain(<your query here>);

它显示如下:

  1   SingletonNode                1   * ROOT
  2   EnumerateCollectionNode      3     - FOR fromItem IN fromCollection   /* full collection scan */
  3   EnumerateCollectionNode      9       - FOR toItem IN toCollection   /* full collection scan */
  4   CalculationNode              9         - LET #3 = (fromItem.`fromAttributeValue` == toItem.`toAttributeValue`)   /* simple expression */   /* collections used: fromItem : fromCollection, toItem : toCollection */
  5   FilterNode                   9         - FILTER #3
  ...
Run Code Online (Sandbox Code Playgroud)

如果你这样做

db.toCollection.ensureIndex({"type":"hash", fields ["toAttributeValue"], unique:false})`
Run Code Online (Sandbox Code Playgroud)

然后将会有一个完整的表集合扫描,fromCollection并且对于每个项目,发现其中有一个哈希查找toCollection,这将更快.一切都会分批进行,所以这应该已经改善了局面.在db._explain()将显示此:

  1   SingletonNode                1   * ROOT
  2   EnumerateCollectionNode      3     - FOR fromItem IN fromCollection   /* full collection scan */
  8   IndexNode                    3       - FOR toItem IN toCollection   /* hash index scan */
Run Code Online (Sandbox Code Playgroud)

要仅处理最近插入的项目fromCollection相对简单:只需将导入时间的时间戳添加到所有顶点,并使用:

FOR fromItem IN fromCollection
    FILTER fromItem.timeStamp > @lastRun
    FOR toItem IN toCollection
        FILTER fromItem.fromAttributeValue == toItem.toAttributeValue
        INSERT { _from: fromItem._id, _to: toItem._id, otherAttributes: {}} INTO edgeCollection
Run Code Online (Sandbox Code Playgroud)

当然,在timeStamp属性中放入一个skiplist索引fromCollection.

这应该可以很好地发现它中的新顶点fromCollection.它将"忽略" toCollection顶点链接的新顶点fromCollection.

您可以通过交换查询中的fromCollection和/ 的角色来发现这些toCollection(不要忘记fromAttributeValuein中的索引fromCollection)并记住只有在顶点是旧的时才放入边缘,如:

FOR toItem IN toCollection
    FILTER toItem.timeStamp > @lastRun
    FOR fromItem IN fromCollection
        FILTER fromItem.fromAttributeValue == toItem.toAttributeValue
        FILTER fromItem.timeStamp <= @lastRun 
        INSERT { _from: fromItem._id, _to: toItem._id, otherAttributes: {}} INTO edgeCollection
Run Code Online (Sandbox Code Playgroud)

这两个一起应该做你想要的.请在这里找到完整的例子.