mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel
This commit is contained in:
commit
f8d2faf8d5
|
@ -3971,6 +3971,34 @@ function DATE_MILLISECOND (value) {
|
|||
// --SECTION-- graph functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief find all paths through a graph, INTERNAL part called recursively
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function GET_SUB_EDGES (edgeCollections, direction, vertexId) {
|
||||
|
||||
if (!Array.isArray(edgeCollections)) {
|
||||
edgeCollections = [edgeCollections];
|
||||
}
|
||||
|
||||
var result = [];
|
||||
edgeCollections.forEach(function (edgeCollection) {
|
||||
if (direction === 1) {
|
||||
result = result.concat(edgeCollection.outEdges(vertexId));
|
||||
}
|
||||
else if (direction === 2) {
|
||||
result = result.concat(edgeCollection.inEdges(vertexId));
|
||||
}
|
||||
else if (direction === 3) {
|
||||
result = result.concat(edgeCollection.edges(vertexId));
|
||||
}
|
||||
});
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief find all paths through a graph, INTERNAL part called recursively
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3993,18 +4021,9 @@ function GRAPH_SUBNODES (searchAttributes, vertexId, visited, edges, vertices, l
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
var subEdges;
|
||||
|
||||
if (searchAttributes.direction === 1) {
|
||||
subEdges = searchAttributes.edgeCollection.outEdges(vertexId);
|
||||
}
|
||||
else if (searchAttributes.direction === 2) {
|
||||
subEdges = searchAttributes.edgeCollection.inEdges(vertexId);
|
||||
}
|
||||
else if (searchAttributes.direction === 3) {
|
||||
subEdges = searchAttributes.edgeCollection.edges(vertexId);
|
||||
}
|
||||
var subEdges = GET_SUB_EDGES(
|
||||
searchAttributes.edgeCollection, searchAttributes.direction, vertexId
|
||||
);
|
||||
|
||||
var i, j, k;
|
||||
for (i = 0; i < subEdges.length; ++i) {
|
||||
|
@ -4125,73 +4144,92 @@ function GRAPH_PATHS (vertices, edgeCollection, direction, followCycles, minLeng
|
|||
function GENERAL_GRAPH_PATHS (graphname, direction, followCycles, minLength, maxLength) {
|
||||
"use strict";
|
||||
|
||||
/*var searchDirection;
|
||||
var searchDirection;
|
||||
direction = direction || "outbound";
|
||||
followCycles = followCycles || false;
|
||||
minLength = minLength || 0;
|
||||
maxLength = maxLength !== undefined ? maxLength : 10;
|
||||
|
||||
|
||||
var graph = DOCUMENT_HANDLE("_graph" + graphname);
|
||||
// check graph exists and load edgeDefintions
|
||||
var graph = DOCUMENT_HANDLE("_graphs/" + graphname);
|
||||
if (!graph) {
|
||||
THROW(INTERNAL.errors.ERROR_ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "GRAPH_PATHS");
|
||||
THROW(INTERNAL.errors.ERROR_GRAPH_INVALID_GRAPH, "GRAPH_EDGES");
|
||||
}
|
||||
|
||||
var vertexCollections = [];
|
||||
var startCollections = [], edgeCollections = [];
|
||||
|
||||
// validate arguments
|
||||
if (direction === "outbound") {
|
||||
searchDirection = 1;
|
||||
graph.__edgeDefinitions.forEach(function (def) {
|
||||
vertexCollections.concat(def.from);
|
||||
});
|
||||
}
|
||||
else if (direction === "inbound") {
|
||||
graph.__edgeDefinitions.forEach(function (def) {
|
||||
vertexCollections.concat(def.to);
|
||||
});
|
||||
searchDirection = 2;
|
||||
}
|
||||
else if (direction === "any") {
|
||||
graph.__edgeDefinitions.forEach(function (def) {
|
||||
vertexCollections.concat(def.to);
|
||||
vertexCollections.concat(def.from);
|
||||
});
|
||||
searchDirection = 3;
|
||||
}
|
||||
else {
|
||||
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "GRAPH_PATHS");
|
||||
}
|
||||
// validate direction and create edgeCollection array.
|
||||
graph.edgeDefinitions.forEach(function (def) {
|
||||
if (direction === "outbound") {
|
||||
searchDirection = 1;
|
||||
def.from.forEach(function (s) {
|
||||
if (startCollections.indexOf(s) === -1) {
|
||||
startCollections.push(s);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (direction === "inbound") {
|
||||
searchDirection = 2;
|
||||
def.to.forEach(function (s) {
|
||||
if (startCollections.indexOf(s) === -1) {
|
||||
startCollections.push(s);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (direction === "any") {
|
||||
def.from.forEach(function (s) {
|
||||
searchDirection = 3;
|
||||
if (startCollections.indexOf(s) === -1) {
|
||||
startCollections.push(s);
|
||||
}
|
||||
});
|
||||
def.to.forEach(function (s) {
|
||||
if (startCollections.indexOf(s) === -1) {
|
||||
startCollections.push(s);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "GRAPH_PATHS");
|
||||
}
|
||||
if (edgeCollections.indexOf(def.collection) === -1) {
|
||||
edgeCollections.push(COLLECTION(def.collection));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if (minLength < 0 || maxLength < 0 || minLength > maxLength) {
|
||||
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "GRAPH_PATHS");
|
||||
}
|
||||
|
||||
|
||||
|
||||
var searchAttributes = {
|
||||
//edgeCollection : COLLECTION(edgeCollection),
|
||||
minLength : minLength,
|
||||
maxLength : maxLength,
|
||||
direction : searchDirection,
|
||||
followCycles : followCycles
|
||||
};
|
||||
|
||||
var result = [ ];
|
||||
var n = vertices.length, i, j;
|
||||
for (i = 0; i < n; ++i) {
|
||||
var vertex = vertices[i];
|
||||
var visited = { };
|
||||
startCollections.forEach(function (startCollection) {
|
||||
|
||||
visited[vertex._id] = true;
|
||||
//GRAPH_SUBNODES (searchAttributes, vertexId, visited, edges, vertices, level) {
|
||||
var connected = GRAPH_SUBNODES(searchAttributes, vertex._id, visited, [ ], [ vertex ], 0);
|
||||
for (j = 0; j < connected.length; ++j) {
|
||||
result.push(connected[j]);
|
||||
var searchAttributes = {
|
||||
edgeCollection : edgeCollections,
|
||||
minLength : minLength,
|
||||
maxLength : maxLength,
|
||||
direction : searchDirection,
|
||||
followCycles : followCycles
|
||||
};
|
||||
|
||||
var vertices = GET_DOCUMENTS(startCollection);
|
||||
var n = vertices.length, i, j;
|
||||
for (i = 0; i < n; ++i) {
|
||||
var vertex = vertices[i];
|
||||
var visited = { };
|
||||
|
||||
visited[vertex._id] = true;
|
||||
var connected = GRAPH_SUBNODES(searchAttributes, vertex._id, visited, [ ], [ vertex ], 0);
|
||||
for (j = 0; j < connected.length; ++j) {
|
||||
result.push(connected[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;*/
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -4800,6 +4838,7 @@ exports.GRAPH_TRAVERSAL = GRAPH_TRAVERSAL;
|
|||
exports.GRAPH_TRAVERSAL_TREE = GRAPH_TRAVERSAL_TREE;
|
||||
exports.GRAPH_EDGES = GRAPH_EDGES;
|
||||
exports.GENERAL_GRAPH_EDGES = GENERAL_GRAPH_EDGES;
|
||||
exports.GENERAL_GRAPH_PATHS = GENERAL_GRAPH_PATHS;
|
||||
exports.GRAPH_NEIGHBORS = GRAPH_NEIGHBORS;
|
||||
exports.NOT_NULL = NOT_NULL;
|
||||
exports.FIRST_LIST = FIRST_LIST;
|
||||
|
|
|
@ -116,13 +116,6 @@ function ahuacatlQueryGeneralEdgesTestSuite() {
|
|||
/// @brief checks EDGES()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//graphname,
|
||||
//startvertex,
|
||||
//direction,
|
||||
//edgeexamples,
|
||||
//collectionRestrictions
|
||||
|
||||
|
||||
testEdgesAny: function () {
|
||||
var actual;
|
||||
|
||||
|
@ -188,11 +181,184 @@ function ahuacatlQueryGeneralEdgesTestSuite() {
|
|||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite for GRAPH_PATHS() function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function ahuacatlQueryGeneralPathsTestSuite() {
|
||||
var vertex = null;
|
||||
var edge = null;
|
||||
|
||||
return {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set up
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
setUp: function () {
|
||||
db._drop("UnitTestsAhuacatlVertex1");
|
||||
db._drop("UnitTestsAhuacatlVertex2");
|
||||
db._drop("UnitTestsAhuacatlVertex3");
|
||||
db._drop("UnitTestsAhuacatlVertex4");
|
||||
db._drop("UnitTestsAhuacatlEdge1");
|
||||
db._drop("UnitTestsAhuacatlEdge2");
|
||||
|
||||
e1 = "UnitTestsAhuacatlEdge1";
|
||||
e2 = "UnitTestsAhuacatlEdge2";
|
||||
|
||||
vertex1 = db._create("UnitTestsAhuacatlVertex1");
|
||||
vertex2 = db._create("UnitTestsAhuacatlVertex2");
|
||||
vertex3 = db._create("UnitTestsAhuacatlVertex3");
|
||||
vertex4 = db._create("UnitTestsAhuacatlVertex4");
|
||||
edge1 = db._createEdgeCollection(e1);
|
||||
edge2 = db._createEdgeCollection(e2);
|
||||
|
||||
var v1 = vertex1.save({ _key: "v1" });
|
||||
var v2 = vertex1.save({ _key: "v2" });
|
||||
var v3 = vertex2.save({ _key: "v3" });
|
||||
var v4 = vertex2.save({ _key: "v4" });
|
||||
var v5 = vertex3.save({ _key: "v5" });
|
||||
var v6 = vertex3.save({ _key: "v6" });
|
||||
var v7 = vertex4.save({ _key: "v7" });
|
||||
|
||||
try {
|
||||
db._collection("_graphs").remove("_graphs/bla3")
|
||||
} catch (err) {
|
||||
}
|
||||
var g = graph._create(
|
||||
"bla3",
|
||||
graph.edgeDefinitions(
|
||||
graph._undirectedRelationDefinition("UnitTestsAhuacatlEdge1", "UnitTestsAhuacatlVertex1"),
|
||||
graph._directedRelationDefinition("UnitTestsAhuacatlEdge2",
|
||||
["UnitTestsAhuacatlVertex1", "UnitTestsAhuacatlVertex2"],
|
||||
["UnitTestsAhuacatlVertex3", "UnitTestsAhuacatlVertex4"]
|
||||
)
|
||||
)
|
||||
);
|
||||
function makeEdge(from, to, collection) {
|
||||
collection.save(from, to, { what: from.split("/")[1] + "->" + to.split("/")[1] });
|
||||
}
|
||||
makeEdge(v1._id, v2._id, g[e1]);
|
||||
makeEdge(v2._id, v1._id, g[e1]);
|
||||
makeEdge(v1._id, v5._id, g[e2]);
|
||||
makeEdge(v2._id, v5._id, g[e2]);
|
||||
makeEdge(v4._id, v7._id, g[e2]);
|
||||
makeEdge(v3._id, v5._id, g[e2]);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tear down
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
tearDown: function () {
|
||||
db._drop("UnitTestsAhuacatlVertex1");
|
||||
db._drop("UnitTestsAhuacatlVertex2");
|
||||
db._drop("UnitTestsAhuacatlVertex3");
|
||||
db._drop("UnitTestsAhuacatlVertex4");
|
||||
db._drop("UnitTestsAhuacatlEdge1");
|
||||
db._drop("UnitTestsAhuacatlEdge2");
|
||||
db._collection("_graphs").remove("_graphs/bla3");
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks EDGES()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testPaths: function () {
|
||||
var actual, result= {}, i = 0, ed;
|
||||
|
||||
actual = getQueryResults("FOR e IN GRAPH_PATHS('bla3') SORT e.source._key,e.destination._key RETURN [e.source._key,e.destination._key,e.edges]");
|
||||
actual.forEach(function (p) {
|
||||
i++;
|
||||
ed = "";
|
||||
p[2].forEach(function (e) {
|
||||
ed += "|" + e._from.split("/")[1] + "->" + e._to.split("/")[1];
|
||||
});
|
||||
result[i + ":" + p[0] + p[1]] = ed;
|
||||
});
|
||||
|
||||
assertEqual(result["1:v1v1"] , "");
|
||||
assertEqual(result["2:v1v2"] , "|v1->v2");
|
||||
assertEqual(result["3:v1v5"] , "|v1->v2|v2->v5");
|
||||
assertEqual(result["4:v1v5"] , "|v1->v5");
|
||||
assertEqual(result["5:v2v1"] , "|v2->v1");
|
||||
assertEqual(result["6:v2v2"] , "");
|
||||
assertEqual(result["7:v2v5"] , "|v2->v5");
|
||||
assertEqual(result["8:v2v5"] , "|v2->v1|v1->v5");
|
||||
assertEqual(result["9:v3v3"] , "");
|
||||
assertEqual(result["10:v3v5"] , "|v3->v5");
|
||||
assertEqual(result["11:v4v4"] , "");
|
||||
assertEqual(result["12:v4v7"] , "|v4->v7");
|
||||
|
||||
|
||||
|
||||
},
|
||||
|
||||
testPathsWithDirectionAnyAndMaxLength1: function () {
|
||||
var actual, result= {}, i = 0, ed;
|
||||
|
||||
actual = getQueryResults("FOR e IN GRAPH_PATHS('bla3', 'any', false , 1 , 1) SORT e.source._key,e.destination._key RETURN [e.source._key,e.destination._key,e.edges]");
|
||||
actual.forEach(function (p) {
|
||||
i++;
|
||||
ed = "";
|
||||
p[2].forEach(function (e) {
|
||||
ed += "|" + e._from.split("/")[1] + "->" + e._to.split("/")[1];
|
||||
});
|
||||
result[i + ":" + p[0] + p[1]] = ed;
|
||||
});
|
||||
|
||||
assertEqual(result["1:v1v2"] , "|v2->v1");
|
||||
assertEqual(result["2:v1v2"] , "|v1->v2");
|
||||
assertEqual(result["3:v1v5"] , "|v1->v5");
|
||||
assertEqual(result["4:v2v1"] , "|v1->v2");
|
||||
assertEqual(result["5:v2v1"] , "|v2->v1");
|
||||
assertEqual(result["6:v2v5"] , "|v2->v5");
|
||||
assertEqual(result["7:v3v5"] , "|v3->v5");
|
||||
assertEqual(result["8:v4v7"] , "|v4->v7");
|
||||
assertEqual(result["9:v5v1"] , "|v1->v5");
|
||||
assertEqual(result["10:v5v2"] , "|v2->v5");
|
||||
assertEqual(result["11:v5v3"] , "|v3->v5");
|
||||
assertEqual(result["12:v7v4"] , "|v4->v7");
|
||||
|
||||
|
||||
},
|
||||
|
||||
testInBoundPaths: function () {
|
||||
var actual, result= {}, i = 0, ed;
|
||||
|
||||
actual = getQueryResults("FOR e IN GRAPH_PATHS('bla3', 'inbound', false, 1) SORT e.source._key,e.destination._key RETURN [e.source._key,e.destination._key,e.edges]");
|
||||
|
||||
actual.forEach(function (p) {
|
||||
i++;
|
||||
ed = "";
|
||||
p[2].forEach(function (e) {
|
||||
ed += "|" + e._from.split("/")[1] + "->" + e._to.split("/")[1];
|
||||
});
|
||||
result[i + ":" + p[0] + p[1]] = ed;
|
||||
});
|
||||
|
||||
assertEqual(result["1:v1v2"] , "|v2->v1");
|
||||
assertEqual(result["2:v2v1"] , "|v1->v2");
|
||||
assertEqual(result["3:v5v1"] , "|v1->v5");
|
||||
assertEqual(result["4:v5v1"] , "|v2->v5|v1->v2");
|
||||
assertEqual(result["5:v5v2"] , "|v1->v5|v2->v1");
|
||||
assertEqual(result["6:v5v2"] , "|v2->v5");
|
||||
assertEqual(result["7:v5v3"] , "|v3->v5");
|
||||
assertEqual(result["8:v7v4"] , "|v4->v7");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes the test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
jsunity.run(ahuacatlQueryGeneralEdgesTestSuite);
|
||||
jsunity.run(ahuacatlQueryGeneralPathsTestSuite);
|
||||
|
||||
return jsunity.done();
|
||||
|
||||
|
|
Loading…
Reference in New Issue