2017-01-09 6 views
0

Ich migriere gerade eine TRAVERSAL-Funktion von arangoDB 2 nach arangoDB 3. Die aql hatte einen benutzerdefinierten leaf-Besucher und eine filterVertices-Option mit einer benutzerdefinierten AQL-Funktion (für spezifischere Filterung).Migration einer filterVertice UDF von ArangoDB 2.8 nach ArangoDB 3

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

Das Blatt Besucher war UDF relativ einfach zu übertragen, da es schafft nur ein benutzerdefiniertes Objekt, aber ich habe Probleme mit dem filterVertices UDF da in arango 3 die Grafikfunktionen wurden entfernt.

Es gibt einige Fälle, wie die unten in der 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'; 
    } 

Meine Frage ist, wie sollte der Pflaume und verstehen sich inklusive unten genau in FILTER Fällen im aql übersetzt werden?

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} 

Wird die Leistung beeinträchtigt werden, wenn ich die UDF wie und übergeben Sie das Ergebnis in einem LET param und ausschließen (Filter), um sie manuell bedienen?

Antwort

2

Generell Sie auf "prune", "exclude" entscheiden können, wenn Sie die Filter auf der Basis des path Objekt (in Ihrem Fall p) Hier wird der Optimierer, dass jeder längerer Weg erkennen, schreiben Sie nicht eine bestimmte Bedingung erfüllen kann. Beispiele hierfür sind:

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

Zuerst stutzen, wenn die zweite Kante FOO nicht über Art. Die zweite wird beschneiden, wenn es eine label != BAR usw. findet nur bestimmten Tiefen Kontrollen oder globale Kontrollen ALL, NONE, ANY kann vom Optimierungsprogramm erkannt werden.

Sie können auf "exclude" entscheiden, ob Sie den Filter auf den Ausgang vertex oder edge definieren, in Ihrem Fall v und d:

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

Die erste wird alle Kanten auszuschließen, Typ „BAR“ haben, die zweite wird nur Knoten mit dem Namen "BAZ" enthalten. In beiden Fällen wird die Traversierung fortgesetzt.

Im Moment gibt es keine Möglichkeit zu sagen PRUNE, INCLUDE.

Die Verwendung einer UDF zur Implementierung der Filterung ist extrem schlecht für die Leistung. Das liegt daran, dass die UDF eine "Black Box" für AQL ist und insbesondere nicht in den Traversal zum Beschneiden optimiert werden kann. Dennoch ist die Leistung der AQL-Traversierung in unseren internen Tests um Größenordnungen besser, weshalb wir uns entschieden haben, diesen Weg zu gehen.

Leider sind UDF-Funktionen etwas flexibler als nur AQL, daher können einige Funktionen nicht in FILTER only-Anweisungen übersetzt werden. Allerdings gibt es immer noch eine Option, diese Traversals auf die gleiche Weise wie vor 3.0 auszuführen, indem Sie einfach den gesamten Traversal als benutzerdefinierte Funktion definieren. Dies sollte die gleiche Leistung wie zuvor haben (der High-Level-Algorithmus ist identisch, aber wir haben viele andere interne Parts in 3.0 geändert, die hier Performance-Nebeneffekte haben).

Dies wird hier näher erläutert: https://docs.arangodb.com/3.1/Manual/Graphs/Traversals/UsingTraversalObjects.html

Und Ihre neue UDF etwa so aussehen sollte und die startVertex als Eingabe:

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 

Wenn Sie benötigen etwas Hilfe bei der Übersetzung von UDF zu FILTER oder um die volle UDF-Traversal-Funktion zu erhalten, kontaktieren Sie uns bitte direkt über die https://groups.google.com/forum/#!forum/arangodb. Wir benötigen möglicherweise einige E-Mails, um alle Details zu sortieren, die Sie benötigen.

+0

So interessant! Ich hatte eine Antwort in dieser Richtung erwartet. Ich musste nur sicher sein, dass ich nichts aus der Dokumentation vermisste. Leider hängen meine Funktionen von Benutzereingaben und Sammlungsergebnissen ab, daher bin ich mir nicht so sicher, wie machbar es wäre, alles in FILTER-Anweisungen zu konvertieren, aber ich bekomme, was du sagst, und ich werde es für die nächste Refactoring-Runde behalten . Ich weiß, es ist ein Longshot, aber wenn Sie es schaffen, "wenn" -Aussagen in die AQL zu integrieren, würde es Tonnen von Flexibilität hinzufügen! Ich verwende die isDeterministic-Option für jetzt nur für zukünftige Updates bereit sein. – GeorgeKaf