1
0
Fork 0

Added edgeExamples functionality to CPPonly Neighbors.

This commit is contained in:
Michael Hackstein 2015-07-23 15:25:50 +02:00
parent 1ae50e026c
commit 84174aa99a
5 changed files with 152 additions and 27 deletions

View File

@ -1582,7 +1582,7 @@ static AqlValue VertexIdsToAqlValue (triagens::arango::AqlTransaction* trx,
CollectionNameResolver const* resolver,
std::unordered_set<VertexId>& ids,
bool includeData = false) {
Json* result = new Json(Json::Array);
Json* result = new Json(Json::Array, ids.size());
if (includeData) {
for (auto& it : ids) {
@ -1609,7 +1609,7 @@ AqlValue Functions::Neighbors (triagens::aql::Query* query,
basics::traverser::NeighborsOptions opts;
if (n < 4 || n > 6) {
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "NEIGHBORS");
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "NEIGHBORS", (int) 4, (int) 6);
}
auto resolver = trx->resolver();
@ -1654,9 +1654,30 @@ AqlValue Functions::Neighbors (triagens::aql::Query* query,
opts.start = v;
}
}
else if (vertexInfo.isObject()) {
if (!vertexInfo.has("_id")) {
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "NEIGHBORS");
}
vertexId = basics::JsonHelper::getStringValue(vertexInfo.get("_id").json(), "");
// TODO tmp can be replaced by Traversal::IdStringToVertexId
size_t split;
char const* str = vertexId.c_str();
if (! TRI_ValidateDocumentIdKeyGenerator(str, &split)) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD);
}
std::string const collectionName = vertexId.substr(0, split);
auto coli = resolver->getCollectionStruct(collectionName);
if (coli == nullptr || collectionName.compare(vColName) != 0) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
}
VertexId v(coli->_cid, const_cast<char*>(str + split + 1));
opts.start = v;
}
else {
// TODO FIXME
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "NEIGHBORS");
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "NEIGHBORS");
}
Json direction = ExtractFunctionParameter(trx, parameters, 3, false);
@ -1681,9 +1702,6 @@ AqlValue Functions::Neighbors (triagens::aql::Query* query,
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "NEIGHBORS");
}
/* Ignored for now
auto examples = ExtractFunctionParameter(trx, parameters, 4, false);
*/
bool includeData = false;
@ -1700,26 +1718,8 @@ AqlValue Functions::Neighbors (triagens::aql::Query* query,
} else {
opts.maxDepth = basics::JsonHelper::getNumericValue<uint64_t>(options.json(), "maxDepth", opts.minDepth);
}
/*
if (options.has("includeData")) {
Json incl = options.get("includeData");
if (! incl.isBoolean() ) {
//TODO Correct Error Message
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "NEIGHBORS");
}
includeData = incl.json()->_value._boolean;
}
if (options.has("minDepth")) {
Json min = options.get("minDepth");
}
if (options.has("maxDepth")) {
}
*/
}
// TODO Parse VertexInfo {_id},"v/1","1" are all valid
std::unordered_set<VertexId> neighbors;
std::vector<EdgeCollectionInfo*> edgeCollectionInfos;
@ -1733,12 +1733,24 @@ AqlValue Functions::Neighbors (triagens::aql::Query* query,
};
TRI_voc_cid_t eCid = resolver->getCollectionId(eColName);
// Function to return constant distance
auto wc = [](TRI_doc_mptr_copy_t& edge) -> double { return 1; };
edgeCollectionInfos.emplace_back(new EdgeCollectionInfo(
EdgeCollectionInfo* eci = new EdgeCollectionInfo(
eCid,
trx->documentCollection(eCid),
wc
));
);
edgeCollectionInfos.emplace_back(eci);
if (n > 4) {
auto edgeExamples = ExtractFunctionParameter(trx, parameters, 4, false);
if (! (edgeExamples.isArray() && edgeExamples.size() == 0) ) {
opts.addEdgeFilter(edgeExamples, eci->getShaper(), eCid);
}
}
TRI_RunNeighborsSearch(
edgeCollectionInfos,

View File

@ -293,6 +293,7 @@ void BasicOptions::addEdgeFilter (v8::Isolate* isolate,
TRI_shaper_t* shaper,
TRI_voc_cid_t const& cid,
string& errorMessage) {
useEdgeFilter = true;
auto it = _edgeFilter.find(cid);
if (example->IsArray()) {
@ -308,6 +309,20 @@ void BasicOptions::addEdgeFilter (v8::Isolate* isolate,
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Insert a new edge matcher object
////////////////////////////////////////////////////////////////////////////////
void BasicOptions::addEdgeFilter (Json const& example,
TRI_shaper_t* shaper,
TRI_voc_cid_t const& cid) {
useEdgeFilter = true;
auto it = _edgeFilter.find(cid);
if (it == _edgeFilter.end()) {
_edgeFilter.emplace(cid, new ExampleMatcher(example.json(), shaper));
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Checks if an edge matches to given examples
////////////////////////////////////////////////////////////////////////////////

View File

@ -171,6 +171,10 @@ namespace triagens {
TRI_voc_cid_t const& cid,
std::string& errorMessage);
void addEdgeFilter (Json const& example,
TRI_shaper_t* shaper,
TRI_voc_cid_t const& cid);
void addVertexFilter (v8::Isolate* isolate,
v8::Handle<v8::Value> const& example,
triagens::arango::ExplicitTransaction* trx,

View File

@ -76,6 +76,9 @@ namespace triagens {
TRI_shaper_t* _shaper;
std::vector<ExampleDefinition> definitions;
void fillExampleDefinition (TRI_json_t const* example,
ExampleDefinition& def);
void fillExampleDefinition (v8::Isolate* isolate,
v8::Handle<v8::Object> const& example,
v8::Handle<v8::Array> const& names,
@ -95,7 +98,7 @@ namespace triagens {
TRI_shaper_t* shaper,
std::string& errorMessage);
ExampleMatcher (TRI_json_t* example,
ExampleMatcher (TRI_json_t const* example,
TRI_shaper_t* shaper);
~ExampleMatcher () {

View File

@ -172,6 +172,58 @@ function ahuacatlQueryEdgesTestSuite () {
assertEqual(actual, [ ]);
assertQueryError(errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, "FOR e IN EDGES(UnitTestsAhuacatlEdge, 'thefox/thefox', 'outbound') SORT e.what RETURN e.what");
}
};
}
function ahuacatlQueryNeighborsTestSuite () {
var vertex = null;
var edge = null;
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
db._drop("UnitTestsAhuacatlVertex");
db._drop("UnitTestsAhuacatlEdge");
vertex = db._create("UnitTestsAhuacatlVertex");
edge = db._createEdgeCollection("UnitTestsAhuacatlEdge");
vertex.save({ _key: "v1", name: "v1" });
vertex.save({ _key: "v2", name: "v2" });
vertex.save({ _key: "v3", name: "v3" });
vertex.save({ _key: "v4", name: "v4" });
vertex.save({ _key: "v5", name: "v5" });
vertex.save({ _key: "v6", name: "v6" });
vertex.save({ _key: "v7", name: "v7" });
function makeEdge (from, to) {
edge.save("UnitTestsAhuacatlVertex/" + from, "UnitTestsAhuacatlVertex/" + to, { what: from + "->" + to, _key: from + "_" + to });
}
makeEdge("v1", "v2");
makeEdge("v1", "v3");
makeEdge("v2", "v3");
makeEdge("v3", "v4");
makeEdge("v3", "v6");
makeEdge("v3", "v7");
makeEdge("v4", "v2");
makeEdge("v7", "v3");
makeEdge("v6", "v3");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
db._drop("UnitTestsAhuacatlVertex");
db._drop("UnitTestsAhuacatlEdge");
},
////////////////////////////////////////////////////////////////////////////////
@ -327,6 +379,44 @@ function ahuacatlQueryEdgesTestSuite () {
return x.name;
});
assertEqual(actual, ["v4", "v6", "v7"]);
},
testNeighborsEdgeExamples : function () {
var actual;
var v3 = "UnitTestsAhuacatlVertex/v3";
var v4 = "UnitTestsAhuacatlVertex/v4";
var v6 = "UnitTestsAhuacatlVertex/v6";
var v7 = "UnitTestsAhuacatlVertex/v7";
var query = "FOR n IN NEIGHBORS(UnitTestsAhuacatlVertex, UnitTestsAhuacatlEdge, @startId"
+ ", 'outbound', @examples) SORT n RETURN n";
// An empty array should let all edges through
actual = getQueryResults(query, {startId: v3, examples: []});
assertEqual(actual, [ v4, v6, v7 ]);
// Should be able to handle exactly one object
actual = getQueryResults(query, {startId: v3, examples: {what: "v3->v4"}});
assertEqual(actual, [ v4 ]);
// Should be able to handle a list of a single object
actual = getQueryResults(query, {startId: v3, examples: [{what: "v3->v4"}]});
assertEqual(actual, [ v4 ]);
// Should be able to handle a list of objects
actual = getQueryResults(query, {startId: v3, examples: [{what: "v3->v4"}, {what: "v3->v6"}]});
assertEqual(actual, [ v4, v6 ]);
// Should be able to handle an id as string
actual = getQueryResults(query, {startId: v3, examples: "UnitTestAhuacatlEdge/v3_v6"});
assertEqual(actual, [ v6 ]);
// Should be able to handle a mix of id and objects
actual = getQueryResults(query, {startId: v3, examples: ["UnitTestAhuacatlEdge/v3_v6", {what: "v3->v4"}]});
assertEqual(actual, [ v4, v6 ]);
// Should be able to handle internal attributes
actual = getQueryResults(query, {startId: v3, examples: {_to: v4}});
assertEqual(actual, [ v4 ]);
}
};
@ -1862,6 +1952,7 @@ function ahuacatlQueryShortestpathErrorsSuite () {
////////////////////////////////////////////////////////////////////////////////
jsunity.run(ahuacatlQueryEdgesTestSuite);
jsunity.run(ahuacatlQueryNeighborsTestSuite);
jsunity.run(ahuacatlQueryPathsTestSuite);
jsunity.run(ahuacatlQueryShortestPathTestSuite);
jsunity.run(ahuacatlQueryTraversalFilterTestSuite);