mirror of https://gitee.com/bigwinds/arangodb
traversal aql
This commit is contained in:
parent
eb7150d815
commit
c99ce5167d
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue