1
0
Fork 0

aql function edges

This commit is contained in:
scottashton 2014-05-19 15:28:05 +02:00
parent d9951b9642
commit 256868bdc2
3 changed files with 387 additions and 3 deletions

View File

@ -703,10 +703,12 @@ TRI_associative_pointer_t* TRI_CreateFunctionsAql (void) {
// graph functions
REGISTER_FUNCTION("PATHS", "GRAPH_PATHS", false, false, "c,h|s,b", &OptimisePaths);
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("TRAVERSAL_TREE", "GRAPH_TRAVERSAL_TREE", false, false, "h,h,s,s,s|a", NULL);
REGISTER_FUNCTION("EDGES", "GRAPH_EDGES", false, false, "h,s,s|l", NULL);
REGISTER_FUNCTION("EDGES", "GRAPH_EDGES", false, false, "h,s,s|l,l", NULL);
REGISTER_FUNCTION("GRAPH_EDGES", "GENERAL_GRAPH_EDGES", false, false, "s,s,s|l,l", NULL);
REGISTER_FUNCTION("NEIGHBORS", "GRAPH_NEIGHBORS", false, false, "h,h,s,s|l", NULL);
// date functions

View File

@ -184,7 +184,8 @@ function FILTER (list, examples) {
var result = [ ], i;
if (examples === undefined || examples === null) {
if (examples === undefined || examples === null ||
(Array.isArray(examples) && examples.length === 0)) {
return list;
}
@ -4116,6 +4117,85 @@ function GRAPH_PATHS (vertices, edgeCollection, direction, followCycles, minLeng
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief find all paths through a graph
////////////////////////////////////////////////////////////////////////////////
function GENERAL_GRAPH_PATHS (graphname, direction, followCycles, minLength, maxLength) {
"use strict";
/*var searchDirection;
direction = direction || "outbound";
followCycles = followCycles || false;
minLength = minLength || 0;
maxLength = maxLength !== undefined ? maxLength : 10;
var graph = DOCUMENT_HANDLE("_graph" + graphname);
if (!graph) {
THROW(INTERNAL.errors.ERROR_ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "GRAPH_PATHS");
}
var vertexCollections = [];
// 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");
}
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 = { };
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]);
}
}
return result;*/
}
////////////////////////////////////////////////////////////////////////////////
/// @brief visitor callback function for traversal
////////////////////////////////////////////////////////////////////////////////
@ -4474,7 +4554,97 @@ function GRAPH_EDGES (edgeCollection,
}
return FILTER(result, examples);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return connected edges
////////////////////////////////////////////////////////////////////////////////
function GENERAL_GRAPH_EDGES (graphname,
startvertex,
direction,
edgeexamples,
collectionRestrictions) {
"use strict";
//check graph exists and load edgeDefintions
var graph = DOCUMENT_HANDLE("_graphs/" + graphname);
if (!graph) {
THROW(INTERNAL.errors.ERROR_GRAPH_INVALID_GRAPH, "EDGES");
}
//check startvertex exists and parse identifier
var start = DOCUMENT_HANDLE(startvertex);
if (!start) {
THROW(INTERNAL.errors.ERROR_ARANGO_DOCUMENT_NOT_FOUND, "EDGES");
}
var startCollection = startvertex.split("/")[0];
var edgeCollections = [];
// validate direction and create edgeCollection array.
if (direction === "outbound") {
graph.edgeDefinitions.forEach(function (def) {
if (def.from.indexOf(startCollection) !== -1 &&
edgeCollections.indexOf(def.collection) === -1) {
edgeCollections.push(def.collection);
}
});
}
else if (direction === "inbound") {
graph.edgeDefinitions.forEach(function (def) {
if (def.to.indexOf(startCollection) !== -1 &&
edgeCollections.indexOf(def.collection) === -1) {
edgeCollections.push(def.collection);
}
});
}
else if (direction === "any") {
graph.edgeDefinitions.forEach(function (def) {
if ((def.from.indexOf(startCollection) !== -1 ||
def.to.indexOf(startCollection) !== -1) &&
edgeCollections.indexOf(def.collection) === -1) {
edgeCollections.push(def.collection);
}
});
}
else {
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "EDGES");
}
if (collectionRestrictions) {
if (typeof collectionRestrictions === "string") {
collectionRestrictions = [collectionRestrictions];
}
edgeCollections.forEach(function (e) {
if (collectionRestrictions.indexOf(e) === -1) {
edgeCollections.splice(edgeCollections.indexOf(e));
}
});
}
//Now get the result.
var result = [];
edgeCollections.forEach(function (c) {
c = COLLECTION(c);
if (direction === "outbound") {
result = result.concat(c.outEdges(startvertex));
}
else if (direction === "inbound") {
result = result.concat(c.inEdges(startvertex));
}
else if (direction === "any") {
result = result.concat(c.edges(startvertex));
}
});
return FILTER(result, edgeexamples);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return connected neighbors
@ -4639,6 +4809,7 @@ exports.GRAPH_SHORTEST_PATH = GRAPH_SHORTEST_PATH;
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.GRAPH_NEIGHBORS = GRAPH_NEIGHBORS;
exports.NOT_NULL = NOT_NULL;
exports.FIRST_LIST = FIRST_LIST;

View File

@ -0,0 +1,211 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief tests for query language, graph functions
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var jsunity = require("jsunity");
var db = require("org/arangodb").db;
var graph = require("org/arangodb/general-graph");
var errors = require("internal").errors;
var helper = require("org/arangodb/aql-helper");
var getQueryResults = helper.getQueryResults;
var assertQueryError = helper.assertQueryError;
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite for EDGES() function
////////////////////////////////////////////////////////////////////////////////
function ahuacatlQueryGeneralEdgesTestSuite () {
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");
vertex1 = db._create("UnitTestsAhuacatlVertex1");
vertex2 = db._create("UnitTestsAhuacatlVertex2");
vertex3 = db._create("UnitTestsAhuacatlVertex3");
vertex4 = db._create("UnitTestsAhuacatlVertex4");
edge1 = db._createEdgeCollection("UnitTestsAhuacatlEdge1");
edge2 = db._createEdgeCollection("UnitTestsAhuacatlEdge2");
vertex1.save({ _key: "v1" });
vertex1.save({ _key: "v2" });
vertex2.save({ _key: "v3" });
vertex2.save({ _key: "v4" });
vertex3.save({ _key: "v5" });
vertex3.save({ _key: "v6" });
vertex4.save({ _key: "v7" });
function makeEdge (from, to, collection) {
collection.save(from, to, { what: from.split("/")[1] + "->" + to.split("/")[1] });
}
makeEdge("UnitTestsAhuacatlVertex1/v1", "UnitTestsAhuacatlVertex1/v2", edge1);
makeEdge("UnitTestsAhuacatlVertex1/v2", "UnitTestsAhuacatlVertex1/v1", edge1);
makeEdge("UnitTestsAhuacatlVertex1/v1", "UnitTestsAhuacatlVertex3/v5", edge2);
makeEdge("UnitTestsAhuacatlVertex1/v2", "UnitTestsAhuacatlVertex3/v5", edge2);
makeEdge("UnitTestsAhuacatlVertex2/v3", "UnitTestsAhuacatlVertex3/v6", edge2);
makeEdge("UnitTestsAhuacatlVertex2/v4", "UnitTestsAhuacatlVertex4/v7", edge2);
makeEdge("UnitTestsAhuacatlVertex2/v3", "UnitTestsAhuacatlVertex3/v5", edge2);
try {
db._collection("_graphs").remove("_graphs/bla3")
} catch (err) {
}
graph._create(
"bla3",
graph.edgeDefinitions(
graph._undirectedRelationDefinition("UnitTestsAhuacatlEdge1", "UnitTestsAhuacatlVertex1"),
graph._directedRelationDefinition("UnitTestsAhuacatlEdge2",
["UnitTestsAhuacatlVertex1", "UnitTestsAhuacatlVertex2"],
["UnitTestsAhuacatlVertex3", "UnitTestsAhuacatlVertex4"]
)
)
);
},
////////////////////////////////////////////////////////////////////////////////
/// @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()
////////////////////////////////////////////////////////////////////////////////
//graphname,
//startvertex,
//direction,
//edgeexamples,
//collectionRestrictions
testEdgesAny : function () {
var actual;
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', 'any') SORT e.what RETURN e.what");
assertEqual(actual, [ "v1->v2", "v1->v5", "v2->v1" ]);
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', 'any' , [] , ['UnitTestsAhuacatlEdge1']) SORT e.what RETURN e.what");
assertEqual(actual, [ "v1->v2", "v2->v1" ]);
actual = getQueryResults("FOR e IN GRAPH_EDGES('bla3', 'UnitTestsAhuacatlVertex1/v1', 'any' , [{'what' : 'v2->v1'}]) SORT e.what RETURN e.what");
assertEqual(actual, [ "v2->v1" ]);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks EDGES()
////////////////////////////////////////////////////////////////////////////////
/*testEdgesIn : function () {
var actual;
actual = getQueryResults("FOR e IN GRAPH_EDGES(UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v1', 'inbound') SORT e.what RETURN e.what");
assertEqual(actual, [ ]);
actual = getQueryResults("FOR e IN GRAPH_EDGES(UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v2', 'inbound') SORT e.what RETURN e.what");
assertEqual(actual, [ "v1->v2", "v4->v2" ]);
actual = getQueryResults("FOR e IN GRAPH_EDGES(UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v3', 'inbound') SORT e.what RETURN e.what");
assertEqual(actual, [ "v1->v3", "v2->v3", "v6->v3", "v7->v3" ]);
actual = getQueryResults("FOR e IN GRAPH_EDGES(UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v3', 'inbound') SORT e.what RETURN e.what");
assertEqual(actual, [ "v1->v3", "v2->v3", "v6->v3", "v7->v3" ]);
actual = getQueryResults("FOR e IN GRAPH_EDGES(UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v8', 'inbound') SORT e.what RETURN e.what");
assertEqual(actual, [ ]);
actual = getQueryResults("FOR e IN GRAPH_EDGES(UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/thefox', 'inbound') SORT e.what RETURN e.what");
assertEqual(actual, [ ]);
assertQueryError(errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, "FOR e IN GRAPH_EDGES(UnitTestsAhuacatlEdge, 'thefox/thefox', 'inbound') SORT e.what RETURN e.what");
},
*/
////////////////////////////////////////////////////////////////////////////////
/// @brief checks EDGES()
////////////////////////////////////////////////////////////////////////////////
/*testEdgesOut : function () {
var actual;
actual = getQueryResults("FOR e IN GRAPH_EDGES(UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v1', 'outbound') SORT e.what RETURN e.what");
assertEqual(actual, [ "v1->v2", "v1->v3" ]);
actual = getQueryResults("FOR e IN GRAPH_EDGES(UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v2', 'outbound') SORT e.what RETURN e.what");
assertEqual(actual, [ "v2->v3" ]);
actual = getQueryResults("FOR e IN GRAPH_EDGES(UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v3', 'outbound') SORT e.what RETURN e.what");
assertEqual(actual, [ "v3->v4", "v3->v6", "v3->v7" ]);
actual = getQueryResults("FOR e IN GRAPH_EDGES(UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v8', 'outbound') SORT e.what RETURN e.what");
assertEqual(actual, [ ]);
actual = getQueryResults("FOR e IN GRAPH_EDGES(UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v5', 'outbound') SORT e.what RETURN e.what");
assertEqual(actual, [ ]);
actual = getQueryResults("FOR e IN GRAPH_EDGES(UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/thefox', 'outbound') SORT e.what RETURN e.what");
assertEqual(actual, [ ]);
assertQueryError(errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, "FOR e IN GRAPH_EDGES(UnitTestsAhuacatlEdge, 'thefox/thefox', 'outbound') SORT e.what RETURN e.what");
}
*/
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
jsunity.run(ahuacatlQueryGeneralEdgesTestSuite);
return jsunity.done();
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End: