我目前正在将一个TRAVERSAL函数从arangoDB 2迁移到arangoDB 3.aql有一个自定义叶子访问者和一个带有自定义AQL函数的filterVertices选项(用于更具体的过滤)。
FOR result IN TRAVERSAL(
page,
menu,
"page/99999999999999",
"inbound",
{filterVertices : "udf::customFilter", visitor : "udf::customVisitor", }
) RETURN result
叶子访问者UDF相对容易传输,因为它只是创建一个自定义对象,但是我遇到了filterVertices UDF的问题,因为在arango 3中,图形函数已被删除。
有一些情况,例如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中的FILTER案例中翻译修剪和排除?
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参数并手动排除(过滤)它们会影响性能吗?
答案 0 :(得分: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
,第二个就会修剪
等等
优化程序只能识别特定的深度检查或全局检查ALL
,NONE
,ANY
。
如果您在"exclude"
或vertex
输出中定义过滤器,则可以edge
决定v
和d
:
FILTER d.type != "BAR"
FILTER v.name == "BAZ"
第一个将排除所有类型为“BAR”的边,第二个将仅包含名称为“BAZ”的顶点。在这两种情况下,遍历都会继续。
现在没有选项可以说PRUNE, INCLUDE
。
使用UDF仅实现过滤对性能非常不利。这是因为UDF是AQL的“黑盒子”,特别是无法优化到Traversal进行修剪。 在我们的内部测试中,AQL遍历的性能仍然是几个数量级,这就是我们决定采用这种方式的原因。
不幸的是,UDF函数仅比AQL稍微灵活一些,因此可能有些函数无法转换为FILTER
语句。
但是,通过将整个Traversal定义为用户定义的函数,仍然可以选择以与3.0之前相同的方式执行这些遍历。这应该具有与以前相同的性能(高级算法是相同的,但我们在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直接与我们联系。我们可能需要一些邮件来整理您需要的所有细节。