1
0
Fork 0

Fixed minor inconsistency in AQL NEIGHBORS and adapted tests to the new version. It will now Return the list of vertices. not the pair<edge, vertex> any more

This commit is contained in:
Michael Hackstein 2015-05-22 15:30:24 -07:00
parent e1813327b5
commit 0b8e9eb59c
5 changed files with 216 additions and 204 deletions

View File

@ -381,86 +381,51 @@ unique_ptr<ArangoDBPathFinder::Path> TRI_RunShortestPathSearch (
} }
vector<VertexId> TRI_RunNeighborsSearch ( vector<VertexId> TRI_RunNeighborsSearch (
v8::Isolate* isolate, vector<EdgeCollectionInfo*>& collectionInfos,
TRI_vocbase_t* vocbase,
std::string const& vertexCollectionName,
std::string const& edgeCollectionName,
std::string const& startVertex,
CollectionNameResolver const* resolver,
TRI_document_collection_t* ecol,
NeighborsOptions& opts NeighborsOptions& opts
) { ) {
// Transform string ids to VertexIds
// Needs refactoring!
size_t split;
char const* str = startVertex.c_str();
vector<VertexId> result; vector<VertexId> result;
if (!TRI_ValidateDocumentIdKeyGenerator(str, &split)) {
// TODO Error Handling
return result;
}
string collectionName = startVertex.substr(0, split);
auto coli = resolver->getCollectionStruct(collectionName);
if (coli == nullptr) {
// collection not found
throw TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
}
if (opts.distinct) { if (opts.distinct) {
unordered_set<VertexId> distinct; unordered_set<VertexId> distinct;
if (opts.direction == "any") { if (opts.direction == TRI_EDGE_IN || opts.direction == TRI_EDGE_ANY) {
auto edges = TRI_LookupEdgesDocumentCollection(ecol, TRI_edge_direction_e dir = TRI_EDGE_IN;
TRI_EDGE_IN, coli->_cid, const_cast<char*>(str + split + 1)); for (auto col : collectionInfos) {
for (size_t j = 0; j < edges.size(); ++j) { auto edges = col->getEdges(dir, opts.start);
distinct.insert(extractFromId(edges[j])); for (size_t j = 0; j < edges.size(); ++j) {
distinct.insert(extractFromId(edges[j]));
}
} }
edges = TRI_LookupEdgesDocumentCollection(ecol, }
TRI_EDGE_OUT, coli->_cid, const_cast<char*>(str + split + 1)); if (opts.direction == TRI_EDGE_OUT || opts.direction == TRI_EDGE_ANY) {
for (size_t j = 0; j < edges.size(); ++j) { TRI_edge_direction_e dir = TRI_EDGE_OUT;
distinct.insert(extractToId(edges[j])); for (auto col : collectionInfos) {
} auto edges = col->getEdges(dir, opts.start);
} else if (opts.direction == "inbound") { for (size_t j = 0; j < edges.size(); ++j) {
auto edges = TRI_LookupEdgesDocumentCollection(ecol, distinct.insert(extractToId(edges[j]));
TRI_EDGE_IN, coli->_cid, const_cast<char*>(str + split + 1)); }
for (size_t j = 0; j < edges.size(); ++j) {
distinct.insert(extractFromId(edges[j]));
}
} else {
auto edges = TRI_LookupEdgesDocumentCollection(ecol,
TRI_EDGE_OUT, coli->_cid, const_cast<char*>(str + split + 1));
for (size_t j = 0; j < edges.size(); ++j) {
distinct.insert(extractToId(edges[j]));
} }
} }
copy(distinct.begin(), distinct.end(), back_inserter(result)); copy(distinct.begin(), distinct.end(), back_inserter(result));
} else { } else {
if (opts.direction == "any") { if (opts.direction == TRI_EDGE_IN || opts.direction == TRI_EDGE_ANY) {
auto edges = TRI_LookupEdgesDocumentCollection(ecol, TRI_edge_direction_e dir = TRI_EDGE_IN;
TRI_EDGE_IN, coli->_cid, const_cast<char*>(str + split + 1)); for (auto col : collectionInfos) {
for (size_t j = 0; j < edges.size(); ++j) { auto edges = col->getEdges(dir, opts.start);
result.push_back(extractFromId(edges[j])); for (size_t j = 0; j < edges.size(); ++j) {
result.push_back(extractFromId(edges[j]));
}
} }
edges = TRI_LookupEdgesDocumentCollection(ecol, }
TRI_EDGE_OUT, coli->_cid, const_cast<char*>(str + split + 1)); if (opts.direction == TRI_EDGE_OUT || opts.direction == TRI_EDGE_ANY) {
for (size_t j = 0; j < edges.size(); ++j) { TRI_edge_direction_e dir = TRI_EDGE_OUT;
result.push_back(extractToId(edges[j])); for (auto col : collectionInfos) {
} auto edges = col->getEdges(dir, opts.start);
} else if (opts.direction == "inbound") { for (size_t j = 0; j < edges.size(); ++j) {
auto edges = TRI_LookupEdgesDocumentCollection(ecol, result.push_back(extractToId(edges[j]));
TRI_EDGE_IN, coli->_cid, const_cast<char*>(str + split + 1)); }
for (size_t j = 0; j < edges.size(); ++j) {
result.push_back(extractFromId(edges[j]));
}
} else {
auto edges = TRI_LookupEdgesDocumentCollection(ecol,
TRI_EDGE_OUT, coli->_cid, const_cast<char*>(str + split + 1));
for (size_t j = 0; j < edges.size(); ++j) {
result.push_back(extractToId(edges[j]));
} }
} }
} }
return result; return result;
}; };

View File

@ -44,10 +44,10 @@ struct VertexId {
TRI_voc_cid_t cid; TRI_voc_cid_t cid;
char const* key; char const* key;
VertexId() : cid(0), key(nullptr) { VertexId () : cid(0), key(nullptr) {
} }
VertexId( TRI_voc_cid_t cid, char const* key) VertexId (TRI_voc_cid_t cid, char const* key)
: cid(cid), key(key) { : cid(cid), key(key) {
} }
@ -77,7 +77,7 @@ struct VertexFilterInfo {
TRI_transaction_collection_t* col; TRI_transaction_collection_t* col;
triagens::arango::ExampleMatcher* matcher; triagens::arango::ExampleMatcher* matcher;
VertexFilterInfo( VertexFilterInfo (
triagens::arango::ExplicitTransaction* trx, triagens::arango::ExplicitTransaction* trx,
TRI_transaction_collection_t* col, TRI_transaction_collection_t* col,
triagens::arango::ExampleMatcher* matcher triagens::arango::ExampleMatcher* matcher
@ -126,7 +126,7 @@ namespace triagens {
useEdgeFilter(false) { useEdgeFilter(false) {
} }
void addEdgeFilter( void addEdgeFilter (
v8::Isolate* isolate, v8::Isolate* isolate,
v8::Handle<v8::Object> const& example, v8::Handle<v8::Object> const& example,
TRI_shaper_t* shaper, TRI_shaper_t* shaper,
@ -134,7 +134,7 @@ namespace triagens {
std::string& errorMessage std::string& errorMessage
); );
void addVertexFilter( void addVertexFilter (
v8::Isolate* isolate, v8::Isolate* isolate,
v8::Handle<v8::Object> const& example, v8::Handle<v8::Object> const& example,
triagens::arango::ExplicitTransaction* trx, triagens::arango::ExplicitTransaction* trx,
@ -144,20 +144,21 @@ namespace triagens {
std::string& errorMessage std::string& errorMessage
); );
void addFinalVertex(VertexId& v); void addFinalVertex (VertexId& v);
bool matchesEdge(EdgeId& e, TRI_doc_mptr_copy_t* edge) const; bool matchesEdge (EdgeId& e, TRI_doc_mptr_copy_t* edge) const;
bool matchesVertex(VertexId& v) const;
bool matchesVertex (VertexId& v) const;
}; };
struct NeighborsOptions {
std::string direction;
bool distinct;
NeighborsOptions() : struct NeighborsOptions {
direction("outbound"), TRI_edge_direction_e direction;
distinct(false) { bool distinct;
VertexId start;
NeighborsOptions () :
direction(TRI_EDGE_OUT),
distinct(true) {
} }
}; };
@ -292,13 +293,7 @@ std::unique_ptr<ArangoDBPathFinder::Path> TRI_RunShortestPathSearch (
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
std::vector<VertexId> TRI_RunNeighborsSearch ( std::vector<VertexId> TRI_RunNeighborsSearch (
v8::Isolate* isolate, std::vector<EdgeCollectionInfo*>& collectionInfos,
TRI_vocbase_t* vocbase,
std::string const& vertexCollectionName,
std::string const& edgeCollectionName,
std::string const& startVertex,
triagens::arango::CollectionNameResolver const* resolver,
TRI_document_collection_t* ecol,
triagens::basics::traverser::NeighborsOptions& opts triagens::basics::traverser::NeighborsOptions& opts
); );

View File

@ -1669,7 +1669,7 @@ static ExplicitTransaction* beginTransaction(
// Abort the collection and free the pointers // Abort the collection and free the pointers
trx->abort(); trx->abort();
delete trx; delete trx;
throw e; throw;
} }
return trx; return trx;
} }
@ -1854,7 +1854,7 @@ static void JS_QueryShortestPath (const v8::FunctionCallbackInfo<v8::Value>& arg
unordered_set<string> vertexCollectionNames; unordered_set<string> vertexCollectionNames;
v8ArrayToStrings(args[0], vertexCollectionNames); v8ArrayToStrings(args[0], vertexCollectionNames);
// get the vertex collections // get the edge collections
if (! args[1]->IsArray()) { if (! args[1]->IsArray()) {
TRI_V8_THROW_TYPE_ERROR("expecting array for <edgecollections[]>"); TRI_V8_THROW_TYPE_ERROR("expecting array for <edgecollections[]>");
} }
@ -2033,8 +2033,15 @@ static void JS_QueryShortestPath (const v8::FunctionCallbackInfo<v8::Value>& arg
} }
} }
opts.start = idStringToVertexId(resolver, startVertex); try {
opts.end = idStringToVertexId(resolver, targetVertex); opts.start = idStringToVertexId(resolver, startVertex);
opts.end = idStringToVertexId(resolver, targetVertex);
} catch (int e) {
// Id string might have illegal collection name
trx->finish(e);
delete trx;
TRI_V8_THROW_EXCEPTION(e);
}
try { try {
path = TRI_RunShortestPathSearch( path = TRI_RunShortestPathSearch(
@ -2074,54 +2081,27 @@ static v8::Handle<v8::Value> vertexIdsToV8(v8::Isolate* isolate,
CollectionNameResolver const* resolver, CollectionNameResolver const* resolver,
vector<VertexId>& ids, vector<VertexId>& ids,
unordered_map<TRI_voc_cid_t, CollectionBarrierInfo>& barriers, unordered_map<TRI_voc_cid_t, CollectionBarrierInfo>& barriers,
bool includeData = false, bool includeData = false) {
bool includeDuplicates = true) {
v8::EscapableHandleScope scope(isolate); v8::EscapableHandleScope scope(isolate);
v8::Handle<v8::Object> result = v8::Object::New(isolate); uint32_t const vn = static_cast<uint32_t>(ids.size());
v8::Handle<v8::Array> vertices = v8::Array::New(isolate, static_cast<int>(vn));
if (includeDuplicates) { if (includeData) {
uint32_t const vn = static_cast<uint32_t>(ids.size()); for (uint32_t j = 0; j < vn; ++j) {
v8::Handle<v8::Array> vertices = v8::Array::New(isolate, static_cast<int>(vn)); vertices->Set(j, vertexIdToData(isolate, resolver, trx, barriers, ids[j]));
if (includeData) {
for (uint32_t j = 0; j < vn; ++j) {
vertices->Set(j, vertexIdToData(isolate, resolver, trx, barriers, ids[j]));
}
} else {
for (uint32_t j = 0; j < vn; ++j) {
vertices->Set(j, vertexIdToString(isolate, resolver, ids[j]));
}
} }
result->Set(TRI_V8_STRING("vertices"), vertices);
return scope.Escape<v8::Value>(result);
} else { } else {
// set<VertexId> uniqueIds(ids.begin(), ids.end()); for (uint32_t j = 0; j < vn; ++j) {
// TODO vertices->Set(j, vertexIdToString(isolate, resolver, ids[j]));
auto uniqueIds = ids;
uint32_t const vn = static_cast<uint32_t>(uniqueIds.size());
v8::Handle<v8::Array> vertices = v8::Array::New(isolate, static_cast<int>(vn));
auto iterator = uniqueIds.begin();
if (includeData) {
for (uint32_t j = 0; j < vn; ++j) {
vertices->Set(j, vertexIdToData(isolate, resolver, trx, barriers, *iterator));
++iterator;
}
} else {
for (uint32_t j = 0; j < vn; ++j) {
vertices->Set(j, vertexIdToString(isolate, resolver, *iterator));
++iterator;
}
} }
result->Set(TRI_V8_STRING("vertices"), vertices);
return scope.Escape<v8::Value>(result);
} }
return scope.Escape<v8::Value>(vertices);
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief Executes a shortest Path Traversal /// @brief Executes a Neighbors computation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static void JS_QueryNeighbors (const v8::FunctionCallbackInfo<v8::Value>& args) { static void JS_QueryNeighbors (const v8::FunctionCallbackInfo<v8::Value>& args) {
@ -2129,74 +2109,88 @@ static void JS_QueryNeighbors (const v8::FunctionCallbackInfo<v8::Value>& args)
v8::HandleScope scope(isolate); v8::HandleScope scope(isolate);
if (args.Length() < 3 || args.Length() > 4) { if (args.Length() < 3 || args.Length() > 4) {
TRI_V8_THROW_EXCEPTION_USAGE("CPP_NEIGHBORS(<vertexcollection>, <edgecollection>, <start>, <options>)"); TRI_V8_THROW_EXCEPTION_USAGE("CPP_NEIGHBORS(<vertexcollections[]>, <edgecollections[]>, <start>, <options>)");
} }
TRI_vocbase_t* vocbase; // get the vertex collections
if (! args[0]->IsArray()) {
vocbase = GetContextVocBase(isolate); TRI_V8_THROW_TYPE_ERROR("expecting array for <vertexcollections[]>");
// get the vertex collection
if (! args[0]->IsString()) {
TRI_V8_THROW_TYPE_ERROR("expecting string for <vertexcollection>");
} }
string vertexCollectionName = TRI_ObjectToString(args[0]); unordered_set<string> vertexCollectionNames;
v8ArrayToStrings(args[0], vertexCollectionNames);
// get the edge collection // get the edge collections
if (! args[1]->IsString()) { if (! args[1]->IsArray()) {
TRI_V8_THROW_TYPE_ERROR("expecting string for <edgecollection>"); TRI_V8_THROW_TYPE_ERROR("expecting array for <edgecollections[]>");
} }
string const edgeCollectionName = TRI_ObjectToString(args[1]); unordered_set<string> edgeCollectionNames;
v8ArrayToStrings(args[1], edgeCollectionNames);
vocbase = GetContextVocBase(isolate); TRI_vocbase_t* vocbase = GetContextVocBase(isolate);
if (vocbase == nullptr) { if (vocbase == nullptr) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND); TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
} }
if (! args[2]->IsString()) { if (! args[2]->IsString()) {
TRI_V8_THROW_TYPE_ERROR("expecting string for <startVertex>"); TRI_V8_THROW_TYPE_ERROR("expecting id for <startVertex>");
} }
string const startVertex = TRI_ObjectToString(args[2]); string const startVertex = TRI_ObjectToString(args[2]);
// TODO Option parsing
traverser::NeighborsOptions opts; traverser::NeighborsOptions opts;
bool includeData = false;
v8::Handle<v8::Object> vertexExample;
if (args.Length() == 4) { if (args.Length() == 4) {
if (! args[3]->IsObject()) { if (! args[3]->IsObject()) {
TRI_V8_THROW_TYPE_ERROR("expecting json for <options>"); TRI_V8_THROW_TYPE_ERROR("expecting json for <options>");
} }
v8::Handle<v8::Object> options = args[3]->ToObject(); v8::Handle<v8::Object> options = args[3]->ToObject();
v8::Local<v8::String> keyDirection = TRI_V8_ASCII_STRING("direction");
v8::Local<v8::String> keyDistinct= TRI_V8_ASCII_STRING("distinct");
// Parse direction
v8::Local<v8::String> keyDirection = TRI_V8_ASCII_STRING("direction");
if (options->Has(keyDirection) ) { if (options->Has(keyDirection) ) {
opts.direction = TRI_ObjectToString(options->Get(keyDirection)); string dir = TRI_ObjectToString(options->Get(keyDirection));
if ( opts.direction != "outbound" if (dir == "outbound") {
&& opts.direction != "inbound" opts.direction = TRI_EDGE_OUT;
&& opts.direction != "any" } else if (dir == "inbound") {
) { opts.direction = TRI_EDGE_IN;
} else if (dir == "any") {
opts.direction = TRI_EDGE_ANY;
} else {
TRI_V8_THROW_TYPE_ERROR("expecting direction to be 'outbound', 'inbound' or 'any'"); TRI_V8_THROW_TYPE_ERROR("expecting direction to be 'outbound', 'inbound' or 'any'");
} }
} }
// Parse use distinct
v8::Local<v8::String> keyDistinct= TRI_V8_ASCII_STRING("distinct");
if (options->Has(keyDistinct) ) { if (options->Has(keyDistinct) ) {
opts.distinct = TRI_ObjectToBoolean(options->Get(keyDistinct)); opts.distinct = TRI_ObjectToBoolean(options->Get(keyDistinct));
} }
// Parse includeData
v8::Local<v8::String> keyIncludeData = TRI_V8_ASCII_STRING("includeData");
if (options->Has(keyIncludeData)) {
includeData = TRI_ObjectToBoolean(options->Get(keyIncludeData));
}
} }
vector<TRI_voc_cid_t> readCollections; vector<TRI_voc_cid_t> readCollections;
vector<TRI_voc_cid_t> writeCollections; vector<TRI_voc_cid_t> writeCollections;
V8ResolverGuard resolverGuard(vocbase); V8ResolverGuard resolverGuard(vocbase);
CollectionNameResolver const* resolver = resolverGuard.getResolver();
readCollections.push_back(resolver->getCollectionId(vertexCollectionName));
readCollections.push_back(resolver->getCollectionId(edgeCollectionName));
ExplicitTransaction* trx = nullptr; ExplicitTransaction* trx = nullptr;
int res = 0; int res = 0;
CollectionNameResolver const* resolver = resolverGuard.getResolver();
for (auto it : edgeCollectionNames) {
readCollections.push_back(resolver->getCollectionId(it));
}
for (auto it : vertexCollectionNames) {
readCollections.push_back(resolver->getCollectionId(it));
}
unordered_map<TRI_voc_cid_t, CollectionBarrierInfo> barriers; unordered_map<TRI_voc_cid_t, CollectionBarrierInfo> barriers;
// Start the transaction // Start the transaction
@ -2204,21 +2198,43 @@ static void JS_QueryNeighbors (const v8::FunctionCallbackInfo<v8::Value>& args)
trx = beginTransaction(vocbase, readCollections, writeCollections, trx = beginTransaction(vocbase, readCollections, writeCollections,
resolver, barriers); resolver, barriers);
} catch (int e) { } catch (int e) {
// Nothing to clean up. Throw the error to V8
TRI_V8_THROW_EXCEPTION(e); TRI_V8_THROW_EXCEPTION(e);
} }
TRI_voc_cid_t edgeCid = resolver->getCollectionId(edgeCollectionName); vector<EdgeCollectionInfo*> edgeCollectionInfos;
TRI_ASSERT(barriers.find(edgeCid) != barriers.end()); for(auto it : edgeCollectionNames) {
auto cid = resolver->getCollectionId(it);
auto colObj = barriers.find(cid)->second.col->_collection->_collection;
edgeCollectionInfos.push_back(new EdgeCollectionInfo(
cid,
colObj,
HopWeightCalculator()
));
}
vector<VertexCollectionInfo*> vertexCollectionInfos;
for(auto it : vertexCollectionNames) {
auto cid = resolver->getCollectionId(it);
auto colObj = barriers.find(cid)->second.col;
vertexCollectionInfos.push_back(new VertexCollectionInfo(
cid,
colObj
));
}
try {
opts.start = idStringToVertexId(resolver, startVertex);
} catch (int e) {
// Id string might have illegal collection name
trx->finish(e);
delete trx;
TRI_V8_THROW_EXCEPTION(e);
}
vector<VertexId> neighbors; vector<VertexId> neighbors;
try { try {
neighbors = TRI_RunNeighborsSearch( neighbors = TRI_RunNeighborsSearch(
isolate, edgeCollectionInfos,
vocbase,
vertexCollectionName,
edgeCollectionName,
startVertex,
resolver,
barriers.find(edgeCid)->second.col->_collection->_collection,
opts opts
); );
} catch (int e) { } catch (int e) {
@ -2227,7 +2243,7 @@ static void JS_QueryNeighbors (const v8::FunctionCallbackInfo<v8::Value>& args)
TRI_V8_THROW_EXCEPTION(e); TRI_V8_THROW_EXCEPTION(e);
} }
auto result = vertexIdsToV8(isolate, trx, resolver, neighbors, barriers, true); auto result = vertexIdsToV8(isolate, trx, resolver, neighbors, barriers, includeData);
trx->finish(res); trx->finish(res);
delete trx; delete trx;

View File

@ -6490,15 +6490,17 @@ function AQL_NEIGHBORS (vertexCollection,
edgeCollection, edgeCollection,
vertex, vertex,
direction, direction,
examples) { examples,
options) {
'use strict'; 'use strict';
vertex = TO_ID(vertex, vertexCollection); vertex = TO_ID(vertex, vertexCollection);
/* options = options || {};
options.direction = direction;
options.examples = examples;
if (examples === undefined) { if (examples === undefined) {
return [CPP_NEIGHBORS(vertexCollection, edgeCollection, vertex, {direction: direction})]; return CPP_NEIGHBORS([vertexCollection], [edgeCollection], vertex, options);
} }
*/
var edges = AQL_EDGES(edgeCollection, vertex, direction); var edges = AQL_EDGES(edgeCollection, vertex, direction);
return FILTERED_EDGES(edges, vertex, direction, examples); return FILTERED_EDGES(edges, vertex, direction, examples);

View File

@ -150,26 +150,38 @@ function ahuacatlQueryEdgesTestSuite () {
testNeighborsAny : function () { testNeighborsAny : function () {
var actual; var actual;
var v1 = "UnitTestsAhuacatlVertex/v1";
var v2 = "UnitTestsAhuacatlVertex/v2";
var v3 = "UnitTestsAhuacatlVertex/v3";
var v4 = "UnitTestsAhuacatlVertex/v4";
var v5 = "UnitTestsAhuacatlVertex/v5";
var v6 = "UnitTestsAhuacatlVertex/v6";
var v7 = "UnitTestsAhuacatlVertex/v7";
var v8 = "UnitTestsAhuacatlVertex/v8";
var theFox = "UnitTestsAhuacatlVertex/thefox";
var queryStart = "FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, '";
var queryEnd = "', 'any') SORT n RETURN n";
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v1', 'any') SORT n.vertex._key RETURN [ n.vertex._key, n.edge.what ]"); actual = getQueryResults(queryStart + v1 + queryEnd);
assertEqual(actual, [ [ "v2", "v1->v2" ], [ "v3", "v1->v3" ] ]); assertEqual(actual, [ v2, v3 ]);
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v2', 'any') SORT n.vertex._key RETURN [ n.vertex._key, n.edge.what ]"); actual = getQueryResults(queryStart + v2 + queryEnd);
assertEqual(actual, [ [ "v1", "v1->v2" ], [ "v3", "v2->v3" ], [ "v4", "v4->v2" ] ]); assertEqual(actual, [ v1, v3, v4 ]);
// v6 and v7 are neighbors twice
actual = getQueryResults(queryStart + v3 + queryEnd);
assertEqual(actual, [ v1, v2, v4, v6, v7 ]);
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v3', 'any') SORT n.vertex._key, n.edge.what RETURN [ n.vertex._key, n.edge.what ]"); actual = getQueryResults(queryStart + v8 + queryEnd);
assertEqual(actual, [ [ "v1", "v1->v3"], [ "v2", "v2->v3" ], [ "v4", "v3->v4" ], [ "v6", "v3->v6" ], [ "v6", "v6->v3"], [ "v7", "v3->v7" ], [ "v7", "v7->v3" ] ]);
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v8', 'any') SORT n.vertex._key RETURN n.vertex._key");
assertEqual(actual, [ ]); assertEqual(actual, [ ]);
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v5', 'any') SORT n.vertex._key RETURN n.vertex._key"); actual = getQueryResults(queryStart + v5 + queryEnd);
assertEqual(actual, [ ]); assertEqual(actual, [ ]);
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/thefox', 'any') SORT n.vertex._key RETURN n.vertex._key"); actual = getQueryResults(queryStart + theFox + queryEnd);
assertEqual(actual, [ ]); assertEqual(actual, [ ]);
assertQueryError(errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, "FOR e IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'thefox/thefox', 'any') SORT n.vertex._key RETURN n.vertex._key"); assertQueryError(errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, queryStart + "thefox/thefox" + queryEnd);
}, },
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -178,26 +190,37 @@ function ahuacatlQueryEdgesTestSuite () {
testNeighborsIn : function () { testNeighborsIn : function () {
var actual; var actual;
var v1 = "UnitTestsAhuacatlVertex/v1";
var v2 = "UnitTestsAhuacatlVertex/v2";
var v3 = "UnitTestsAhuacatlVertex/v3";
var v4 = "UnitTestsAhuacatlVertex/v4";
var v5 = "UnitTestsAhuacatlVertex/v5";
var v6 = "UnitTestsAhuacatlVertex/v6";
var v7 = "UnitTestsAhuacatlVertex/v7";
var v8 = "UnitTestsAhuacatlVertex/v8";
var theFox = "UnitTestsAhuacatlVertex/thefox";
var queryStart = "FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, '";
var queryEnd = "', 'inbound') SORT n RETURN n";
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v1', 'inbound') SORT n.vertex._key RETURN [ n.vertex._key, n.edge.what ]"); actual = getQueryResults(queryStart + v1 + queryEnd);
assertEqual(actual, [ ]); assertEqual(actual, [ ]);
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v2', 'inbound') SORT n.vertex._key RETURN [ n.vertex._key, n.edge.what ]"); actual = getQueryResults(queryStart + v2 + queryEnd);
assertEqual(actual, [ [ "v1", "v1->v2" ], [ "v4", "v4->v2" ] ]); assertEqual(actual, [v1, v4]);
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v3', 'inbound') SORT n.vertex._key RETURN [ n.vertex._key, n.edge.what ]"); actual = getQueryResults(queryStart + v3 + queryEnd);
assertEqual(actual, [ [ "v1", "v1->v3"], [ "v2", "v2->v3" ], [ "v6", "v6->v3"], [ "v7", "v7->v3" ] ]); assertEqual(actual, [v1, v2, v6, v7]);
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v8', 'inbound') SORT n.vertex._key RETURN n.vertex._key"); actual = getQueryResults(queryStart + v8 + queryEnd);
assertEqual(actual, [ ]); assertEqual(actual, [ ]);
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v5', 'inbound') SORT n.vertex._key RETURN n.vertex._key"); actual = getQueryResults(queryStart + v5 + queryEnd);
assertEqual(actual, [ ]); assertEqual(actual, [ ]);
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/thefox', 'inbound') SORT n.vertex._key RETURN n.vertex._key"); actual = getQueryResults(queryStart + theFox + queryEnd);
assertEqual(actual, [ ]); assertEqual(actual, [ ]);
assertQueryError(errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, "FOR e IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'thefox/thefox', 'inbound') SORT n.vertex._key RETURN n.vertex._key"); assertQueryError(errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, queryStart + "thefox/thefox" + queryEnd);
}, },
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -234,26 +257,37 @@ function ahuacatlQueryEdgesTestSuite () {
testNeighborsOut : function () { testNeighborsOut : function () {
var actual; var actual;
var v1 = "UnitTestsAhuacatlVertex/v1";
var v2 = "UnitTestsAhuacatlVertex/v2";
var v3 = "UnitTestsAhuacatlVertex/v3";
var v4 = "UnitTestsAhuacatlVertex/v4";
var v5 = "UnitTestsAhuacatlVertex/v5";
var v6 = "UnitTestsAhuacatlVertex/v6";
var v7 = "UnitTestsAhuacatlVertex/v7";
var v8 = "UnitTestsAhuacatlVertex/v8";
var theFox = "UnitTestsAhuacatlVertex/thefox";
var queryStart = "FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, '";
var queryEnd = "', 'outbound') SORT n RETURN n";
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v1', 'outbound') SORT n.vertex._key RETURN [ n.vertex._key, n.edge.what ]"); actual = getQueryResults(queryStart + v1 + queryEnd);
assertEqual(actual, [ [ "v2", "v1->v2" ], [ "v3", "v1->v3" ] ]); assertEqual(actual, [ v2, v3 ]);
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v2', 'outbound') SORT n.vertex._key RETURN [ n.vertex._key, n.edge.what ]"); actual = getQueryResults(queryStart + v2 + queryEnd);
assertEqual(actual, [ [ "v3", "v2->v3" ] ]); assertEqual(actual, [ v3 ]);
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v3', 'outbound') SORT n.vertex._key RETURN n.vertex._key"); actual = getQueryResults(queryStart + v3 + queryEnd);
assertEqual(actual, [ "v4", "v6", "v7" ]); assertEqual(actual, [ v4, v6, v7 ]);
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v8', 'outbound') SORT n.vertex._key RETURN n.vertex._key"); actual = getQueryResults(queryStart + v8 + queryEnd);
assertEqual(actual, [ ]);
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/v5', 'outbound') SORT n.vertex._key RETURN n.vertex._key");
assertEqual(actual, [ ]); assertEqual(actual, [ ]);
actual = getQueryResults("FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'UnitTestsAhuacatlVertex/thefox', 'outbound') SORT n.vertex._key RETURN n.vertex._key"); actual = getQueryResults(queryStart + v5 + queryEnd);
assertEqual(actual, [ ]); assertEqual(actual, [ ]);
assertQueryError(errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, "FOR e IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, 'thefox/thefox', 'outbound') SORT n.vertex._key RETURN n.vertex._key"); actual = getQueryResults(queryStart + theFox + queryEnd);
assertEqual(actual, [ ]);
assertQueryError(errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, queryStart + "thefox/thefox" + queryEnd);
} }
}; };