mirror of https://gitee.com/bigwinds/arangodb
Added edgeExamples functionality to CPPonly Neighbors.
This commit is contained in:
parent
1ae50e026c
commit
84174aa99a
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 () {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue