1
0
Fork 0

traversal aql

This commit is contained in:
scottashton 2014-05-20 15:55:07 +02:00
parent eb7150d815
commit c99ce5167d
3 changed files with 251 additions and 39 deletions

View File

@ -706,7 +706,9 @@ TRI_associative_pointer_t* TRI_CreateFunctionsAql (void) {
REGISTER_FUNCTION("GRAPH_PATHS", "GENERAL_GRAPH_PATHS", false, false, "s|s,b,n,n", &OptimisePaths);
REGISTER_FUNCTION("SHORTEST_PATH", "GRAPH_SHORTEST_PATH", false, false, "h,h,s,s,s|a", NULL);
REGISTER_FUNCTION("TRAVERSAL", "GRAPH_TRAVERSAL", false, false, "h,h,s,s|a", NULL);
REGISTER_FUNCTION("GRAPH_TRAVERSAL", "GENERAL_GRAPH_TRAVERSAL", false, false, "s,s,s|a", NULL);
REGISTER_FUNCTION("TRAVERSAL_TREE", "GRAPH_TRAVERSAL_TREE", false, false, "h,h,s,s,s|a", NULL);
REGISTER_FUNCTION("GRAPH_TRAVERSAL_TREE", "GENERAL_GRAPH_TRAVERSAL_TREE", false, false, "s,s,s,s|a", NULL);
REGISTER_FUNCTION("EDGES", "GRAPH_EDGES", false, false, "h,s,s|l", NULL);
REGISTER_FUNCTION("GRAPH_EDGES", "GENERAL_GRAPH_EDGES", false, false, "s,s,s|lza,ls", NULL);
REGISTER_FUNCTION("NEIGHBORS", "GRAPH_NEIGHBORS", false, false, "h,h,s,s|l", NULL);

View File

@ -4329,40 +4329,37 @@ function TRAVERSAL_CHECK_EXAMPLES_TYPEWEIGHTS (examples, func) {
});
}
////////////////////////////////////////////////////////////////////////////////
/// @brief tranform key to id
////////////////////////////////////////////////////////////////////////////////
function TO_ID (vertex, collection) {
"use strict";
if (vertex === 'object' && vertex.hasOwnProperty('_id')) {
return vertex._id;
}
if (vertex.indexOf('/') === -1 && collection) {
return collection + '/' + vertex;
}
return vertex;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief traverse a graph
////////////////////////////////////////////////////////////////////////////////
function TRAVERSAL_FUNC (func,
vertexCollection,
edgeCollection,
datasource,
startVertex,
endVertex,
direction,
params) {
"use strict";
if (startVertex === 'object' && startVertex.hasOwnProperty('_id')) {
startVertex = startVertex._id;
}
if (startVertex.indexOf('/') === -1) {
startVertex = vertexCollection + '/' + startVertex;
}
if (endVertex !== undefined) {
if (endVertex === 'object' && endVertex.hasOwnProperty('_id')) {
endVertex = endVertex._id;
}
if (endVertex.indexOf('/') === -1) {
endVertex = vertexCollection + '/' + endVertex;
}
}
vertexCollection = COLLECTION(vertexCollection);
edgeCollection = COLLECTION(edgeCollection);
if (params === undefined) {
params = { };
}
@ -4388,7 +4385,7 @@ function TRAVERSAL_FUNC (func,
var config = {
distance: params.distance,
connect: params.connect,
datasource: TRAVERSAL.collectionDatasourceFactory(edgeCollection),
datasource: datasource,
trackPaths: params.paths || false,
visitor: params.visitor,
maxDepth: params.maxDepth,
@ -4492,10 +4489,9 @@ function GRAPH_SHORTEST_PATH (vertexCollection,
}
return TRAVERSAL_FUNC("SHORTEST_PATH",
vertexCollection,
edgeCollection,
startVertex,
endVertex,
TRAVERSAL.collectionDatasourceFactory(COLLECTION(edgeCollection)),
TO_ID(startVertex, vertexCollection),
TO_ID(endVertex, vertexCollection),
direction,
params);
}
@ -4518,14 +4514,39 @@ function GRAPH_TRAVERSAL (vertexCollection,
params.visitor = TRAVERSAL_VISITOR;
return TRAVERSAL_FUNC("TRAVERSAL",
vertexCollection,
edgeCollection,
startVertex,
TRAVERSAL.collectionDatasourceFactory(COLLECTION(edgeCollection)),
TO_ID(startVertex, vertexCollection),
undefined,
direction,
params);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief traverse a graph
////////////////////////////////////////////////////////////////////////////////
function GENERAL_GRAPH_TRAVERSAL (graphName,
startVertex,
direction,
params) {
"use strict";
if (params === undefined) {
params = { };
}
params.visitor = TRAVERSAL_VISITOR;
return TRAVERSAL_FUNC("TRAVERSAL",
TRAVERSAL.generalGraphDatasourceFactory(graphName),
TO_ID(startVertex),
undefined,
direction,
params);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief traverse a graph and create a hierarchical result
/// this function uses the same setup as the TRAVERSE() function but will use
@ -4552,9 +4573,8 @@ function GRAPH_TRAVERSAL_TREE (vertexCollection,
params.connect = connectName;
var result = TRAVERSAL_FUNC("TRAVERSAL_TREE",
vertexCollection,
edgeCollection,
startVertex,
TRAVERSAL.collectionDatasourceFactory(COLLECTION(edgeCollection)),
TO_ID(startVertex, vertexCollection),
undefined,
direction,
params);
@ -4565,6 +4585,44 @@ function GRAPH_TRAVERSAL_TREE (vertexCollection,
return [ result[0][params.connect] ];
}
////////////////////////////////////////////////////////////////////////////////
/// @brief traverse a graph and create a hierarchical result
/// this function uses the same setup as the TRAVERSE() function but will use
/// a different visitor to create the result
////////////////////////////////////////////////////////////////////////////////
function GENERAL_GRAPH_TRAVERSAL_TREE (graphName,
startVertex,
direction,
connectName,
params) {
"use strict";
if (connectName === "") {
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "TRAVERSAL_TREE");
}
if (params === undefined) {
params = { };
}
params.visitor = TRAVERSAL_TREE_VISITOR;
params.connect = connectName;
var result = TRAVERSAL_FUNC("TRAVERSAL_TREE",
TRAVERSAL.generalGraphDatasourceFactory(graphName),
TO_ID(startVertex),
undefined,
direction,
params);
if (result.length === 0) {
return [ ];
}
return [ result[0][params.connect] ];
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return connected edges
////////////////////////////////////////////////////////////////////////////////
@ -4836,6 +4894,8 @@ exports.GRAPH_PATHS = GRAPH_PATHS;
exports.GRAPH_SHORTEST_PATH = GRAPH_SHORTEST_PATH;
exports.GRAPH_TRAVERSAL = GRAPH_TRAVERSAL;
exports.GRAPH_TRAVERSAL_TREE = GRAPH_TRAVERSAL_TREE;
exports.GENERAL_GRAPH_TRAVERSAL = GENERAL_GRAPH_TRAVERSAL;
exports.GENERAL_GRAPH_TRAVERSAL_TREE = GENERAL_GRAPH_TRAVERSAL_TREE;
exports.GRAPH_EDGES = GRAPH_EDGES;
exports.GENERAL_GRAPH_EDGES = GENERAL_GRAPH_EDGES;
exports.GENERAL_GRAPH_PATHS = GENERAL_GRAPH_PATHS;

View File

@ -262,7 +262,7 @@ function ahuacatlQueryGeneralPathsTestSuite() {
},
////////////////////////////////////////////////////////////////////////////////
/// @brief checks EDGES()
/// @brief checks GRAPH_PATHS()
////////////////////////////////////////////////////////////////////////////////
testPaths: function () {
@ -352,11 +352,161 @@ function ahuacatlQueryGeneralPathsTestSuite() {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite for GRAPH_TRAVERSAL() function
////////////////////////////////////////////////////////////////////////////////
function ahuacatlQueryGeneralTraversalTestSuite() {
var vertex = null;
var edge = null;
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp: function () {
db._drop("UnitTests_Berliner");
db._drop("UnitTests_Hamburger");
db._drop("UnitTests_Frankfurter");
db._drop("UnitTests_Leipziger");
db._drop("UnitTests_KenntAnderenBerliner");
db._drop("UnitTests_KenntAnderen");
KenntAnderenBerliner = "UnitTests_KenntAnderenBerliner";
KenntAnderen = "UnitTests_KenntAnderen";
Berlin = db._create("UnitTests_Berliner");
Hamburg = db._create("UnitTests_Hamburger");
Frankfurt = db._create("UnitTests_Frankfurter");
Leipzig = db._create("UnitTests_Leipziger");
db._createEdgeCollection(KenntAnderenBerliner);
db._createEdgeCollection(KenntAnderen);
var Anton = Berlin.save({ _key: "Anton" , gender : "male"});
var Berta = Berlin.save({ _key: "Berta" , gender : "female"});
var Caesar = Hamburg.save({ _key: "Caesar" , gender : "male"});
var Dieter = Hamburg.save({ _key: "Dieter" , gender : "male"});
var Emil = Frankfurt.save({ _key: "Emil" , gender : "male"});
var Fritz = Frankfurt.save({ _key: "Fritz" , gender : "male"});
var Gerda = Leipzig.save({ _key: "Gerda" , gender : "female"});
try {
db._collection("_graphs").remove("_graphs/werKenntWen")
} catch (err) {
}
var g = graph._create(
"werKenntWen",
graph.edgeDefinitions(
graph._undirectedRelationDefinition(KenntAnderenBerliner, "UnitTests_Berliner"),
graph._directedRelationDefinition(KenntAnderen,
["UnitTests_Hamburger", "UnitTests_Frankfurter", "UnitTests_Berliner", "UnitTests_Leipziger"],
["UnitTests_Hamburger", "UnitTests_Frankfurter", "UnitTests_Berliner", "UnitTests_Leipziger"]
)
)
);
function makeEdge(from, to, collection) {
collection.save(from, to, { what: from.split("/")[1] + "->" + to.split("/")[1] });
}
makeEdge(Berta._id, Anton._id, g[KenntAnderenBerliner]);
makeEdge(Caesar._id, Anton._id, g[KenntAnderen]);
makeEdge(Caesar._id, Berta._id, g[KenntAnderen]);
makeEdge(Berta._id, Gerda._id, g[KenntAnderen]);
makeEdge(Gerda._id, Dieter._id, g[KenntAnderen]);
makeEdge(Dieter._id, Emil._id, g[KenntAnderen]);
makeEdge(Emil._id, Fritz._id, g[KenntAnderen]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown: function () {
db._drop("UnitTests_Berliner");
db._drop("UnitTests_Hamburger");
db._drop("UnitTests_Frankfurter");
db._drop("UnitTests_Leipziger");
db._drop("UnitTests_KenntAnderenBerliner");
db._drop("UnitTests_KenntAnderen");
db._collection("_graphs").remove("_graphs/werKenntWen");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief checks GRAPH_TRAVERSAL()
////////////////////////////////////////////////////////////////////////////////
testGRAPH_TRAVERSALs: function () {
var actual, result= [];
actual = getQueryResults("FOR e IN GRAPH_TRAVERSAL('werKenntWen', 'UnitTests_Hamburger/Caesar', 'outbound') RETURN e");
//require("internal").print(actual);
actual.forEach(function (s) {
result.push(s.vertex._key);
});
//require("internal").print(result)
assertEqual(result, [
"Caesar",
"Anton",
"Berta",
"Anton",
"Gerda",
"Dieter",
"Emil",
"Fritz"
]);
},
testGENERAL_GRAPH_TRAVERSAL_TREE: function () {
var actual, start, middle;
actual = getQueryResults("FOR e IN GRAPH_TRAVERSAL_TREE('werKenntWen', 'UnitTests_Hamburger/Caesar', 'outbound', 'connected') RETURN e");
start = actual[0][0];
assertEqual(start._key, "Caesar");
assertTrue(start.hasOwnProperty("connected"));
assertTrue(start.connected.length === 2);
assertEqual(start.connected[0]._key, "Anton");
assertEqual(start.connected[1]._key, "Berta");
assertTrue(!start.connected[0].hasOwnProperty("connected"));
assertTrue(start.connected[1].hasOwnProperty("connected"));
middle = start.connected[1];
assertTrue(middle.connected.length === 2);
assertEqual(middle.connected[0]._key, "Anton");
assertEqual(middle.connected[1]._key, "Gerda");
assertTrue(!middle.connected[0].hasOwnProperty("connected"));
assertTrue(middle.connected[1].hasOwnProperty("connected"));
middle = middle.connected[1];
assertTrue(middle.connected.length === 1);
assertEqual(middle.connected[0]._key, "Dieter");
middle = middle.connected[0];
assertTrue(middle.connected.length === 1);
assertEqual(middle.connected[0]._key, "Emil");
middle = middle.connected[0];
assertTrue(middle.connected.length === 1);
assertEqual(middle.connected[0]._key, "Fritz");
}
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
jsunity.run(ahuacatlQueryGeneralTraversalTestSuite);
jsunity.run(ahuacatlQueryGeneralEdgesTestSuite);
jsunity.run(ahuacatlQueryGeneralPathsTestSuite);