mirror of https://gitee.com/bigwinds/arangodb
allow specifying minLength and maxLengths for PATHS AQL function
This commit is contained in:
parent
9049753b62
commit
ba783a4584
|
@ -5,7 +5,7 @@ AQL has the following functions to traverse graphs:
|
|||
If you have created a graph in the general-graph module you may want to use
|
||||
[Graph operations](../Aql/GraphOperations.md) instead.
|
||||
|
||||
- *PATHS(vertexcollection, edgecollection, direction, followcycles)*:
|
||||
- *PATHS(vertexcollection, edgecollection, direction, options)*:
|
||||
returns an array of paths through the graph defined by the nodes in the collection
|
||||
*vertexcollection* and edges in the collection *edgecollection*. For each vertex
|
||||
in *vertexcollection*, it will determine the paths through the graph depending on the
|
||||
|
@ -14,8 +14,11 @@ If you have created a graph in the general-graph module you may want to use
|
|||
- *"inbound"*: Follow all paths that lead from another vertex to the current vertex
|
||||
- *"any"*: Combination of *"outbound"* and *"inbound"*
|
||||
The default value for *direction* is *"outbound"*.
|
||||
If *followcycles* is true, cyclic paths will be followed as well. This is turned off by
|
||||
default.
|
||||
If specified, *options* must be a JavaScript object with the following optional attributes:
|
||||
- *minLength*: specifies the minimum length of the paths to be returned. The default is 0.
|
||||
- *maxLength*: specifies the maximum length of the paths to be returned. The default is 10.
|
||||
- *followcycles*: if true, cyclic paths will be followed as well. This is turned off by
|
||||
default.
|
||||
|
||||
The result of the function is an array of paths. Paths of length 0 will also be returned. Each
|
||||
path is a document consisting of the following attributes:
|
||||
|
@ -26,10 +29,10 @@ If you have created a graph in the general-graph module you may want to use
|
|||
|
||||
*Examples*
|
||||
|
||||
PATHS(friends, friendrelations, "outbound", false)
|
||||
PATHS(friends, friendrelations, "outbound")
|
||||
|
||||
FOR p IN PATHS(friends, friendrelations, "outbound")
|
||||
FILTER p.source._id == "123456/123456" && LENGTH(p.edges) == 2
|
||||
FOR p IN PATHS(friends, friendrelations, "outbound", { minLength: 2, maxLength: 2 })
|
||||
FILTER p.source._id == "users/123456"
|
||||
RETURN p.vertices[*].name
|
||||
|
||||
If you have created a graph in the general-graph module you may want to use
|
||||
|
|
|
@ -195,7 +195,7 @@ std::unordered_map<std::string, Function const> const Executor::FunctionNames{
|
|||
{ "FULLTEXT", Function("FULLTEXT", "AQL_FULLTEXT", "h,s,s", false, true, false) },
|
||||
|
||||
// graph functions
|
||||
{ "PATHS", Function("PATHS", "AQL_PATHS", "c,h|s,b", false, true, false) },
|
||||
{ "PATHS", Function("PATHS", "AQL_PATHS", "c,h|s,ba", false, true, false) },
|
||||
{ "GRAPH_PATHS", Function("GRAPH_PATHS", "AQL_GRAPH_PATHS", "s|a", false, true, false) },
|
||||
{ "SHORTEST_PATH", Function("SHORTEST_PATH", "AQL_SHORTEST_PATH", "h,h,s,s,s|a", false, true, false) },
|
||||
{ "GRAPH_SHORTEST_PATH", Function("GRAPH_SHORTEST_PATH", "AQL_GRAPH_SHORTEST_PATH", "s,als,als|a", false, true, false) },
|
||||
|
|
|
@ -4523,15 +4523,22 @@ function SUBNODES (searchAttributes, vertexId, visited, edges, vertices, level)
|
|||
/// @brief find all paths through a graph
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function AQL_PATHS (vertices, edgeCollection, direction, followCycles, minLength, maxLength) {
|
||||
function AQL_PATHS (vertices, edgeCollection, direction, options) {
|
||||
"use strict";
|
||||
|
||||
var searchDirection;
|
||||
|
||||
direction = direction || "outbound";
|
||||
followCycles = followCycles || false;
|
||||
minLength = minLength || 0;
|
||||
maxLength = maxLength !== undefined ? maxLength : 10;
|
||||
|
||||
if (typeof options === "boolean") {
|
||||
options = { followCycles : options };
|
||||
}
|
||||
else if (typeof options !== "object" || Array.isArray(options)) {
|
||||
options = { };
|
||||
}
|
||||
|
||||
var followCycles = options.followCycles || false;
|
||||
var minLength = options.minLength || 0;
|
||||
var maxLength = options.maxLength || 10;
|
||||
|
||||
if (TYPEWEIGHT(vertices) !== TYPEWEIGHT_ARRAY) {
|
||||
WARN("PATHS", INTERNAL.errors.ERROR_QUERY_ARRAY_EXPECTED);
|
||||
|
@ -4539,6 +4546,7 @@ function AQL_PATHS (vertices, edgeCollection, direction, followCycles, minLength
|
|||
}
|
||||
|
||||
// validate arguments
|
||||
var searchDirection;
|
||||
if (direction === "outbound") {
|
||||
searchDirection = 1;
|
||||
}
|
||||
|
|
|
@ -314,6 +314,22 @@ function ahuacatlQueryPathsTestSuite () {
|
|||
assertEqual(docs["Fred"]._id, actual[0].edges[0]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL outbound query using _from, path length 1
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testFromQueryOutboundMaxLength1 : function () {
|
||||
var actual = getQueryResults("FOR p IN PATHS(UnitTestsAhuacatlUsers, UnitTestsAhuacatlUserRelations, \"outbound\", { maxLength: 1 }) FILTER p.edges[0]._from == \"" + docs["John"]._id +"\" RETURN p");
|
||||
assertEqual(1, actual.length);
|
||||
assertEqual(1, actual[0].edges.length);
|
||||
|
||||
assertEqual(docs["John"]._id, actual[0].source._id);
|
||||
assertEqual(docs["Fred"]._id, actual[0].destination._id);
|
||||
|
||||
assertEqual(docs["John"]._id, actual[0].edges[0]._from);
|
||||
assertEqual(docs["Fred"]._id, actual[0].edges[0]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL outbound query using _from, path length 1
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -330,6 +346,22 @@ function ahuacatlQueryPathsTestSuite () {
|
|||
assertEqual(docs["Jacob"]._id, actual[0].edges[0]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL outbound query using _from, path length 1
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testFromQueryOutboundMaxLength2 : function () {
|
||||
var actual = getQueryResults("FOR p IN PATHS(UnitTestsAhuacatlUsers, UnitTestsAhuacatlUserRelations, \"outbound\", { maxLength: 1 }) FILTER p.edges[0]._from == \"" + docs["Fred"]._id +"\" RETURN p");
|
||||
assertEqual(1, actual.length);
|
||||
assertEqual(1, actual[0].edges.length);
|
||||
|
||||
assertEqual(docs["Fred"]._id, actual[0].source._id);
|
||||
assertEqual(docs["Jacob"]._id, actual[0].destination._id);
|
||||
|
||||
assertEqual(docs["Fred"]._id, actual[0].edges[0]._from);
|
||||
assertEqual(docs["Jacob"]._id, actual[0].edges[0]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL outbound query using _to, path length 1
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -346,6 +378,22 @@ function ahuacatlQueryPathsTestSuite () {
|
|||
assertEqual(docs["Fred"]._id, actual[0].edges[0]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL outbound query using _to, path length 1
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testFromQueryOutboundMaxLength3 : function () {
|
||||
var actual = getQueryResults("FOR p IN PATHS(UnitTestsAhuacatlUsers, UnitTestsAhuacatlUserRelations, \"outbound\", { maxLength: 1 }) FILTER p.edges[0]._to == \"" + docs["Fred"]._id +"\" RETURN p");
|
||||
assertEqual(1, actual.length);
|
||||
assertEqual(1, actual[0].edges.length);
|
||||
|
||||
assertEqual(docs["John"]._id, actual[0].source._id);
|
||||
assertEqual(docs["Fred"]._id, actual[0].destination._id);
|
||||
|
||||
assertEqual(docs["John"]._id, actual[0].edges[0]._from);
|
||||
assertEqual(docs["Fred"]._id, actual[0].edges[0]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL outbound query using _from, path length 2
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -364,6 +412,24 @@ function ahuacatlQueryPathsTestSuite () {
|
|||
assertEqual(docs["Jacob"]._id, actual[0].edges[1]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL outbound query using _from, path length 2
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testFromQueryOutboundMaxLength4 : function () {
|
||||
var actual = getQueryResults("FOR p IN PATHS(UnitTestsAhuacatlUsers, UnitTestsAhuacatlUserRelations, \"outbound\", { minLength: 2, maxLength: 2 }) FILTER p.edges[0]._from == \"" + docs["John"]._id +"\" RETURN p");
|
||||
assertEqual(1, actual.length);
|
||||
assertEqual(2, actual[0].edges.length);
|
||||
|
||||
assertEqual(docs["John"]._id, actual[0].source._id);
|
||||
assertEqual(docs["Jacob"]._id, actual[0].destination._id);
|
||||
|
||||
assertEqual(docs["John"]._id, actual[0].edges[0]._from);
|
||||
assertEqual(docs["Fred"]._id, actual[0].edges[0]._to);
|
||||
assertEqual(docs["Fred"]._id, actual[0].edges[1]._from);
|
||||
assertEqual(docs["Jacob"]._id, actual[0].edges[1]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL outbound query using _from
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -373,6 +439,15 @@ function ahuacatlQueryPathsTestSuite () {
|
|||
assertEqual(0, actual.length);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL outbound query using _from
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testFromQueryOutboundMaxLength5 : function () {
|
||||
var actual = getQueryResults("FOR p IN PATHS(UnitTestsAhuacatlUsers, UnitTestsAhuacatlUserRelations, \"outbound\", { maxLength: 2 }) FILTER p.edges[0]._from == \"" + docs["Jacob"]._id +"\" RETURN p");
|
||||
assertEqual(0, actual.length);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL outbound query using _to
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -382,6 +457,15 @@ function ahuacatlQueryPathsTestSuite () {
|
|||
assertEqual(0, actual.length);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL outbound query using _to
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testFromQueryOutboundMaxLength6 : function () {
|
||||
var actual = getQueryResults("FOR p IN PATHS(UnitTestsAhuacatlUsers, UnitTestsAhuacatlUserRelations, \"outbound\", { maxLength: 2 }) FILTER p.edges[0]._to == \"" + docs["John"]._id +"\" RETURN p");
|
||||
assertEqual(0, actual.length);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL inbound query using _from, path length 1
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -398,6 +482,22 @@ function ahuacatlQueryPathsTestSuite () {
|
|||
assertEqual(docs["Fred"]._id, actual[0].edges[0]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL inbound query using _from, path length 1
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testFromQueryInboundMaxLength1 : function () {
|
||||
var actual = getQueryResults("FOR p IN PATHS(UnitTestsAhuacatlUsers, UnitTestsAhuacatlUserRelations, \"inbound\", { maxLength: 1 }) FILTER p.edges[0]._from == \"" + docs["John"]._id +"\" RETURN p");
|
||||
assertEqual(1, actual.length);
|
||||
assertEqual(1, actual[0].edges.length);
|
||||
|
||||
assertEqual(docs["Fred"]._id, actual[0].source._id);
|
||||
assertEqual(docs["John"]._id, actual[0].destination._id);
|
||||
|
||||
assertEqual(docs["John"]._id, actual[0].edges[0]._from);
|
||||
assertEqual(docs["Fred"]._id, actual[0].edges[0]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL inbound query using _from, path length 1
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -414,6 +514,22 @@ function ahuacatlQueryPathsTestSuite () {
|
|||
assertEqual(docs["Jacob"]._id, actual[0].edges[0]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL inbound query using _from, path length 1
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testFromQueryInboundMaxLength2 : function () {
|
||||
var actual = getQueryResults("FOR p IN PATHS(UnitTestsAhuacatlUsers, UnitTestsAhuacatlUserRelations, \"inbound\", { maxLength: 1 }) FILTER p.edges[0]._from == \"" + docs["Fred"]._id +"\" RETURN p");
|
||||
assertEqual(1, actual.length);
|
||||
assertEqual(1, actual[0].edges.length);
|
||||
|
||||
assertEqual(docs["Jacob"]._id, actual[0].source._id);
|
||||
assertEqual(docs["Fred"]._id, actual[0].destination._id);
|
||||
|
||||
assertEqual(docs["Fred"]._id, actual[0].edges[0]._from);
|
||||
assertEqual(docs["Jacob"]._id, actual[0].edges[0]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL inbound query using _to, path length 1
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -430,6 +546,22 @@ function ahuacatlQueryPathsTestSuite () {
|
|||
assertEqual(docs["Fred"]._id, actual[0].edges[0]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL inbound query using _to, path length 1
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testFromQueryInboundMaxLength3 : function () {
|
||||
var actual = getQueryResults("FOR p IN PATHS(UnitTestsAhuacatlUsers, UnitTestsAhuacatlUserRelations, \"inbound\", { maxLength: 1 }) FILTER p.edges[0]._to == \"" + docs["Fred"]._id +"\" RETURN p");
|
||||
assertEqual(1, actual.length);
|
||||
assertEqual(1, actual[0].edges.length);
|
||||
|
||||
assertEqual(docs["Fred"]._id, actual[0].source._id);
|
||||
assertEqual(docs["John"]._id, actual[0].destination._id);
|
||||
|
||||
assertEqual(docs["John"]._id, actual[0].edges[0]._from);
|
||||
assertEqual(docs["Fred"]._id, actual[0].edges[0]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL inbound query using _from, path length 1
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -449,6 +581,72 @@ function ahuacatlQueryPathsTestSuite () {
|
|||
assertEqual(docs["Fred"]._id, actual[0].edges[1]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL inbound query using _from, path length 1
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testFromQueryInboundMaxLength4 : function () {
|
||||
var actual = getQueryResults("FOR p IN PATHS(UnitTestsAhuacatlUsers, UnitTestsAhuacatlUserRelations, \"inbound\", { minLength: 2, maxLength: 2 }) FILTER p.edges[LENGTH(p.edges) - 1]._from == \"" + docs["John"]._id +"\" RETURN p");
|
||||
assertEqual(1, actual.length);
|
||||
assertEqual(2, actual[0].edges.length);
|
||||
|
||||
assertEqual(docs["Jacob"]._id, actual[0].source._id);
|
||||
assertEqual(docs["John"]._id, actual[0].destination._id);
|
||||
|
||||
assertEqual(docs["Fred"]._id, actual[0].edges[0]._from);
|
||||
assertEqual(docs["Jacob"]._id, actual[0].edges[0]._to);
|
||||
|
||||
assertEqual(docs["John"]._id, actual[0].edges[1]._from);
|
||||
assertEqual(docs["Fred"]._id, actual[0].edges[1]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL inbound query using _from, path length 2
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testFromQueryInboundMinLength1 : function () {
|
||||
var actual = getQueryResults("FOR p IN PATHS(UnitTestsAhuacatlUsers, UnitTestsAhuacatlUserRelations, \"inbound\", { minLength: 2, maxLength: 2 }) FILTER p.edges[LENGTH(p.edges) - 1]._from == \"" + docs["John"]._id +"\" RETURN p");
|
||||
assertEqual(1, actual.length);
|
||||
assertEqual(2, actual[0].edges.length);
|
||||
|
||||
assertEqual(docs["Jacob"]._id, actual[0].source._id);
|
||||
assertEqual(docs["John"]._id, actual[0].destination._id);
|
||||
|
||||
assertEqual(docs["Fred"]._id, actual[0].edges[0]._from);
|
||||
assertEqual(docs["Jacob"]._id, actual[0].edges[0]._to);
|
||||
|
||||
assertEqual(docs["John"]._id, actual[0].edges[1]._from);
|
||||
assertEqual(docs["Fred"]._id, actual[0].edges[1]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL inbound query using _from, path length 2
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testFromQueryInboundMinLength2 : function () {
|
||||
var actual = getQueryResults("FOR p IN PATHS(UnitTestsAhuacatlUsers, UnitTestsAhuacatlUserRelations, \"inbound\", { minLength: 2 }) FILTER p.edges[LENGTH(p.edges) - 1]._from == \"" + docs["John"]._id +"\" RETURN p");
|
||||
assertEqual(1, actual.length);
|
||||
assertEqual(2, actual[0].edges.length);
|
||||
|
||||
assertEqual(docs["Jacob"]._id, actual[0].source._id);
|
||||
assertEqual(docs["John"]._id, actual[0].destination._id);
|
||||
|
||||
assertEqual(docs["Fred"]._id, actual[0].edges[0]._from);
|
||||
assertEqual(docs["Jacob"]._id, actual[0].edges[0]._to);
|
||||
|
||||
assertEqual(docs["John"]._id, actual[0].edges[1]._from);
|
||||
assertEqual(docs["Fred"]._id, actual[0].edges[1]._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks an AQL inbound query using _from, path length 3
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testFromQueryInboundMinLength3 : function () {
|
||||
var actual = getQueryResults("FOR p IN PATHS(UnitTestsAhuacatlUsers, UnitTestsAhuacatlUserRelations, \"inbound\", { minLength: 3 }) FILTER p.edges[LENGTH(p.edges) - 1]._from == \"" + docs["John"]._id +"\" RETURN p");
|
||||
assertEqual(0, actual.length);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks AQL inbound and outbound queries
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue