2017-01-09 25 views
0

我目前正在将arangoDB 2的TRAVERSAL函数迁移到arangoDB 3.aql有一个自定义叶子访问器和一个filterVertices选项以及一个自定义AQL函数(用于更具体的过滤)。从ArangoDB 2.8迁移过滤器Vertice UDF到ArangoDB 3

FOR result IN TRAVERSAL(
    page, 
    menu, 
    "page/99999999999999", 
    "inbound", 
    {filterVertices : "udf::customFilter", visitor : "udf::customVisitor", } 
) RETURN result 

叶游客UDF相对容易转移,因为它仅仅是创建一个自定义对象,但我有自阿朗戈3图表功能已被删除与filterVertices UDF麻烦。

有一些情况下,像在filterVertices UDF

//check the page status 
    if (mismatch == 1) { 
     //stop traversal and not return mismatched 
     return ['exclude', 'prune']; 
    } else if (mismatch == 2) { 
     //stop but return mismatched 
     return 'prune'; 
    } else { 
     //exclude mismatched but continue 
     return 'exclude'; 
    } 

我的问题下面是一个应该如何剪枝,并排除被过滤器的情况恰好低于AQL翻译?

FOR v, d, p IN 1..10 INBOUND "page/99999999999999" menu 
    LET filtered = CALL('udf::customFilter',v,p) 
    LET result = CALL('udf::customVisitor',v,d,p) 
RETURN {filtered:filtered,result:result} 

请问如果我使用UDF的性能受到影响是手动传递导致LET PARAM和排除(过滤器)呢?

回答

2

一般来说,你可以在"prune", "exclude"决定,当你写基于path对象上的过滤器(在你的情况p) 这里优化器将认识到,任何更长的路径无法满足一定的条件。这里 的例子是:

FILTER p.edges[1].type == 'FOO' 
FILTER p.edges[*].label ALL == 'BAR' 
FILTER p.vertices[*].age ALL >= 18 

首先会修剪每当第二边缘没有类型FOO。 每当它发现一个label != BAR 等 只有特定深度支票或全球检查ALLNONEANY可以被优化器识别的第二会修剪。

您可以在"exclude"决定,如果你定义在vertexedge输出过滤器,你的情况vd

FILTER d.type != "BAR" 
FILTER v.name == "BAZ" 

第一个将排除有型“BAR”所有边缘,第二将只包含名称为“BAZ”的顶点。在这两种情况下,遍历都会继续。

现在没有选择可以说PRUNE, INCLUDE

仅使用UDF来实现过滤对性能而言极其糟糕。这是因为UDF对于AQL来说是一个“黑盒子”,特​​别是不能在遍历中进行修剪优化。 在我们的内部测试中,AQL遍历的性能还是好几个数量级,这就是我们决定这样做的原因。

不幸的是,UDF函数比AQL稍微灵活一点,所以可能有一些函数不能翻译成FILTER only语句。 但是仍然有一个选项可以像以前的3.0一样执行这些遍历,只需将整个Traversal定义为用户定义的函数即可。这应该具有和以前一样的性能(高级算法是相同的,但是我们在3.0中改变了许多其他内部部件,这些部件在这里具有性能副作用)。

这在这里更详细地解释: https://docs.arangodb.com/3.1/Manual/Graphs/Traversals/UsingTraversalObjects.html

,而新的UDF应该大致是这样的,并采取startVertex输入:

var db = require("internal").db; 
var traversal = require("@arangodb/graph/traversal"); 
var config = { 
    datasource: traversal.collectionDatasource("menu"), 
    filter: db._aqlfunctions.document("UDF::CUSTOMFILTER").code, 
    visitor: db._aqlfunctions.document("UDF::CUSTOMVISITOR").code, 
    maxDepth: 1 // has to be defined 
}; 
var result = { 
    visited: { 
    vertices: [ ], 
    paths: [ ] 
    } 
}; 
var traverser = new traversal.Traverser(config); 
traverser.traverse(result, startVertex); 
[...] // Do stuff with result here 

如果你需要一些帮助,从UDF翻译到FILTER或者让遍历UDF正常运行,请通过https://groups.google.com/forum/#!forum/arangodb直接与我们联系。我们可能需要一些邮件来整理你需要的所有细节。

+0

太有意思了!我期待着这样的答案。我只需要确定我没有错过文档中的任何内容。 不幸的是,我的函数依赖于用户输入和收集结果,因此我不太确定在FILTER语句中将其全部转换是多么可行,但是我明白了你的意思,并且我将继续为下一轮重构。 我知道它很长,但如果你设法在AQL中包含“if”语句,它会增加大量的灵活性! 我正在使用isDeterministic选项来为将来的更新做好准备。 – GeorgeKaf