将filterVertice UDF从ArangoDB 2.8迁移到ArangoDB 3

问题描述 投票:0回答:1

我目前正在将 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 情况下应该如何准确翻译 prune 和 except ?

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 参数并手动排除(过滤)它们,性能会受到影响吗?

arangodb nosql
1个回答
2
投票

更新:基于 JavaScript 的遍历不再可用。您可以改用 AQL 的遍历语言构造:https://docs.arangodb.com/3.11/aql/graphs/traversals/


一般来说,当您基于

"prune", "exclude"
对象编写过滤器时,您可以决定
path
(在您的情况下为
p
) 在这里,优化器将认识到任何更长的路径都无法满足特定条件。 这里的例子是:

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

当第二条边不具有类型

FOO
时,First 将进行修剪。 当第二个找到
label != BAR
时就会修剪 ETC。 优化器只能识别特定深度检查或全局检查
ALL
NONE
ANY

如果您在

"exclude"
vertex
输出上定义过滤器,则可以决定使用
edge
,在您的情况下为
v
d

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

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

现在没有办法说

PRUNE, INCLUDE

仅使用UDF来实现过滤对性能来说非常糟糕。这是因为 UDF 是 AQL 的“黑匣子”,尤其不能优化为遍历进行剪枝。 在我们的内部测试中,AQL 遍历的性能仍然要好几个数量级,这就是我们决定这样做的原因。

不幸的是,UDF 函数比仅 AQL 稍微灵活一些,因此可能有一些函数无法转换为

FILTER 
语句。 然而,仍然可以选择以与 3.0 之前相同的方式执行这些遍历,只需将整个遍历定义为用户定义的函数即可。这应该具有与以前相同的性能(高级算法是相同的,但我们在 3.0 中更改了许多其他内部部件,这些部件在这里具有性能副作用)。

您的新 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 与我们联系。我们可能需要一些邮件来整理您需要的所有详细信息。

© www.soinside.com 2019 - 2024. All rights reserved.