mirror of https://gitee.com/bigwinds/arangodb
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:
parent
e1813327b5
commit
0b8e9eb59c
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue