1
0
Fork 0

fun with custom visitors, cont.

This commit is contained in:
Jan Steemann 2015-01-29 01:57:03 +01:00
parent b4ba07f765
commit 699b7e76f6
2 changed files with 96 additions and 26 deletions

View File

@ -144,6 +144,21 @@ instead.
Note: The *connections* function parameter value will contain the edges connected to the
vertex only if *order* was set to *preorder-expander*. Otherwise, the value of this parameter
will be *undefined*.
The following custom visitor functions are predefined and can be used by specifying the function
name in the *visitor* attribute:
- *"_AQL::PROJECTINGVISITOR"*: this visitor will produce an object with the attributes
specified in *data.attributes* for each visited vertex. This can be used to create a
projection of each visited vertex' document.
- *"_AQL::IDVISITOR"*: this visitor will return the _id attribute of each visited vertex.
- *"_AQL::KEYVISITOR"*: this visitor will return the _key attribute of each visited vertex.
- *"_AQL::COUNTINGVISITOR"*: this visitor will return a single number indicating the number
of vertices visited.
- *visitorReturnsResults*: only useful in combination with a custom AQL visitor function. If
set to *true*, the data returned by the visitor will be appended to the result. If set to
@ -151,6 +166,11 @@ instead.
function can modify its *result* parameter value in-place. At the end of the traversal,
*result* is expected to be an array.
- *data*: only useful in combination with a custom AQL visitor function. This attribute can
be used to pass arbitrary data into the custom visitor function. The value contained in the
*data* attribute will be made available to the *visitor* function in the *config.data*
attribute.
By default, the result of the TRAVERSAL function is an array of traversed points. Each point
is an object consisting of the following attributes:
- *vertex*: The vertex at the traversal point

View File

@ -51,6 +51,46 @@ var RegexCache = { };
var UserFunctions = { };
////////////////////////////////////////////////////////////////////////////////
/// @brief prefab traversal visitors
////////////////////////////////////////////////////////////////////////////////
var DefaultVisitors = {
"_AQL::PROJECTINGVISITOR" : {
visitorReturnsResults: true,
func: function (config, result, vertex) {
var values = { };
if (typeof config.data === "object" && Array.isArray(config.data.attributes)) {
config.data.attributes.forEach(function (attribute) {
values[attribute] = vertex[attribute];
});
}
return values;
}
},
"_AQL::IDVISITOR" : {
visitorReturnsResults: true,
func: function (config, result, vertex) {
return vertex._id;
}
},
"_AQL::KEYVISITOR" : {
visitorReturnsResults: true,
func: function (config, result, vertex) {
return vertex._key;
}
},
"_AQL::COUNTINGVISITOR" : {
visitorReturnsResults: false,
func: function (config, result) {
if (result.length === 0) {
result.push(0);
}
result[0]++;
}
}
};
////////////////////////////////////////////////////////////////////////////////
/// @brief type weight used for sorting and comparing
////////////////////////////////////////////////////////////////////////////////
@ -194,25 +234,34 @@ function reloadUserFunctions () {
/// @brief get a user-function by name
////////////////////////////////////////////////////////////////////////////////
function GET_USERFUNCTION (name) {
function GET_USERFUNCTION (name, config) {
var prefix = DB_PREFIX(), reloaded = false;
var key = name.toUpperCase();
if (! UserFunctions.hasOwnProperty(prefix)) {
reloadUserFunctions();
reloaded = true;
}
if (! UserFunctions[prefix].hasOwnProperty(key) && ! reloaded) {
// last chance
reloadUserFunctions();
}
if (! UserFunctions[prefix].hasOwnProperty(key)) {
THROW(null, INTERNAL.errors.ERROR_QUERY_FUNCTION_NOT_FOUND, name);
}
var func;
var func = UserFunctions[prefix][key].func;
if (DefaultVisitors.hasOwnProperty(key)) {
var visitor = DefaultVisitors[key];
func = visitor.func;
config.visitorReturnsResults = visitor.visitorReturnsResults;
}
else {
if (! UserFunctions.hasOwnProperty(prefix)) {
reloadUserFunctions();
reloaded = true;
}
if (! UserFunctions[prefix].hasOwnProperty(key) && ! reloaded) {
// last chance
reloadUserFunctions();
}
if (! UserFunctions[prefix].hasOwnProperty(key)) {
THROW(null, INTERNAL.errors.ERROR_QUERY_FUNCTION_NOT_FOUND, name);
}
func = UserFunctions[prefix][key].func;
}
if (typeof func !== "function") {
THROW(null, INTERNAL.errors.ERROR_QUERY_FUNCTION_NOT_FOUND, name);
@ -225,8 +274,8 @@ function GET_USERFUNCTION (name) {
/// @brief create a user-defined visitor from a function name
////////////////////////////////////////////////////////////////////////////////
function GET_VISITOR (name) {
var func = GET_USERFUNCTION(name);
function GET_VISITOR (name, config) {
var func = GET_USERFUNCTION(name, config);
return function (config, result, vertex, path) {
try {
@ -250,8 +299,8 @@ function GET_VISITOR (name) {
/// @brief create a user-defined filter from a function name
////////////////////////////////////////////////////////////////////////////////
function GET_FILTER (name) {
var func = GET_USERFUNCTION(name);
function GET_FILTER (name, config) {
var func = GET_USERFUNCTION(name, config);
return function (config, vertex, path) {
try {
@ -5059,7 +5108,8 @@ function TRAVERSAL_FUNC (func,
endVertex : endVertex,
weight : params.weight,
defaultWeight : params.defaultWeight,
prefill : params.prefill
prefill : params.prefill,
data: params.data
};
if (typeof params.filter === "function") {
@ -5456,7 +5506,7 @@ function SHORTEST_PATH_PARAMS (params) {
// add user-defined visitor, if specified
if (typeof params.visitor === "string") {
params.visitor = GET_VISITOR(params.visitor);
params.visitor = GET_VISITOR(params.visitor, params);
}
else {
params.visitor = TRAVERSAL_VISITOR;
@ -5464,7 +5514,7 @@ function SHORTEST_PATH_PARAMS (params) {
// add user-defined filter, if specified
if (typeof params.filter === "string") {
params.filter = GET_FILTER(params.filter);
params.filter = GET_FILTER(params.filter, params);
}
if (typeof params.distance === "string") {
@ -5686,7 +5736,7 @@ function TRAVERSAL_PARAMS (params) {
// add user-defined visitor, if specified
if (typeof params.visitor === "string") {
params.visitor = GET_VISITOR(params.visitor);
params.visitor = GET_VISITOR(params.visitor, params);
}
else {
params.visitor = TRAVERSAL_VISITOR;
@ -5694,7 +5744,7 @@ function TRAVERSAL_PARAMS (params) {
// add user-defined filter, if specified
if (typeof params.filter === "string") {
params.filter = GET_FILTER(params.filter);
params.filter = GET_FILTER(params.filter, params);
}
return params;
@ -6045,7 +6095,7 @@ function TRAVERSAL_TREE_PARAMS (params, connectName, func) {
// add user-defined visitor, if specified
if (typeof params.visitor === "string") {
params.visitor = GET_VISITOR(params.visitor);
params.visitor = GET_VISITOR(params.visitor, params);
}
else {
params.visitor = TRAVERSAL_TREE_VISITOR;
@ -6053,7 +6103,7 @@ function TRAVERSAL_TREE_PARAMS (params, connectName, func) {
// add user-defined filter, if specified
if (typeof params.filter === "string") {
params.filter = GET_FILTER(params.filter);
params.filter = GET_FILTER(params.filter, params);
}
params.connect = AQL_TO_STRING(connectName);