1
0
Fork 0

The RestEdges handler now behaves identically to the server side edges() functions. Specifically it does not return duplicate edges any more. Also added a helper function to build an EdgeIndex Lookup from VPackArray.

This commit is contained in:
Michael Hackstein 2016-03-30 10:13:09 +02:00
parent 8761550add
commit 9d70091713
5 changed files with 143 additions and 29 deletions

View File

@ -348,6 +348,61 @@ void EdgeIndex::buildSearchValue(TRI_edge_direction_e dir,
builder.close();
}
void EdgeIndex::buildSearchValueFromArray(TRI_edge_direction_e dir,
VPackSlice const ids,
VPackBuilder& builder) {
TRI_ASSERT(ids.isArray());
builder.openArray();
switch (dir) {
case TRI_EDGE_OUT:
builder.openArray();
for (auto const& id : VPackArrayIterator(ids)) {
if (id.isString()) {
builder.openObject();
builder.add(TRI_SLICE_KEY_EQUAL, id);
builder.close();
}
}
builder.close();
builder.add(VPackValue(VPackValueType::Null));
break;
case TRI_EDGE_IN:
builder.add(VPackValue(VPackValueType::Null));
builder.openArray();
for (auto const& id : VPackArrayIterator(ids)) {
if (id.isString()) {
builder.openObject();
builder.add(TRI_SLICE_KEY_EQUAL, id);
builder.close();
}
}
builder.close();
break;
case TRI_EDGE_ANY:
builder.openArray();
for (auto const& id : VPackArrayIterator(ids)) {
if (id.isString()) {
builder.openObject();
builder.add(TRI_SLICE_KEY_EQUAL, id);
builder.close();
}
}
builder.close();
builder.openArray();
for (auto const& id : VPackArrayIterator(ids)) {
if (id.isString()) {
builder.openObject();
builder.add(TRI_SLICE_KEY_EQUAL, id);
builder.close();
}
}
builder.close();
}
builder.close();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a selectivity estimate for the index
////////////////////////////////////////////////////////////////////////////////

View File

@ -125,6 +125,10 @@ class EdgeIndex final : public Index {
static void buildSearchValue(TRI_edge_direction_e, std::string const&,
arangodb::velocypack::Builder&);
static void buildSearchValueFromArray(TRI_edge_direction_e,
arangodb::velocypack::Slice const,
arangodb::velocypack::Builder&);
public:
//////////////////////////////////////////////////////////////////////////////
/// @brief typedef for hash tables

View File

@ -80,6 +80,63 @@ HttpHandler::status_t RestEdgesHandler::execute() {
return status_t(HANDLER_DONE);
}
bool RestEdgesHandler::getEdgesForVertexList(
VPackSlice const ids,
std::vector<traverser::TraverserExpression*> const& expressions,
TRI_edge_direction_e direction, SingleCollectionTransaction& trx,
VPackBuilder& result, size_t& scannedIndex, size_t& filtered) {
TRI_ASSERT(ids.isArray());
trx.orderDitch(trx.cid()); // will throw when it fails
std::string const collectionName
= trx.resolver()->getCollectionName(trx.cid());
Transaction::IndexHandle indexId = trx.edgeIndexHandle(collectionName);
VPackBuilder searchValueBuilder;
EdgeIndex::buildSearchValueFromArray(direction, ids, searchValueBuilder);
VPackSlice search = searchValueBuilder.slice();
std::shared_ptr<OperationCursor> cursor = trx.indexScan(
collectionName, arangodb::Transaction::CursorType::INDEX, indexId,
search, 0, UINT64_MAX, 1000, false);
if (cursor->failed()) {
THROW_ARANGO_EXCEPTION(cursor->code);
}
auto opRes = std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR);
while (cursor->hasMore()) {
cursor->getMore(opRes);
if (opRes->failed()) {
THROW_ARANGO_EXCEPTION(opRes->code);
}
VPackSlice edges = opRes->slice();
TRI_ASSERT(edges.isArray());
// generate result
scannedIndex += edges.length();
for (auto const& edge : VPackArrayIterator(edges)) {
bool add = true;
if (!expressions.empty()) {
for (auto& exp : expressions) {
if (exp->isEdgeAccess &&
!exp->matchesCheck(&trx, edge)) {
++filtered;
add = false;
break;
}
}
}
if (add) {
result.add(edge);
}
}
}
return true;
}
bool RestEdgesHandler::getEdgesForVertex(
std::string const& id,
std::vector<traverser::TraverserExpression*> const& expressions,
@ -202,7 +259,6 @@ bool RestEdgesHandler::readEdges(
std::string contentType;
arangodb::basics::Json resultDocument(arangodb::basics::Json::Object, 3);
#warning TODO: use vpack
int res = getFilteredEdgesOnCoordinator(
_vocbase->_name, collectionName, vertexString, direction, expressions,
responseCode, contentType, resultDocument);
@ -382,16 +438,13 @@ bool RestEdgesHandler::readEdgesForMultipleVertices() {
resultBuilder.add(VPackValue("edges")); // only key
resultBuilder.openArray();
for (auto const& vertexSlice : VPackArrayIterator(body)) {
if (vertexSlice.isString()) {
std::string vertex = vertexSlice.copyString();
bool ok = getEdgesForVertex(vertex, expressions, direction, trx,
bool ok = getEdgesForVertexList(body, expressions, direction, trx,
resultBuilder, scannedIndex, filtered);
if (!ok) {
// Ignore the error
}
}
if (!ok) {
// Ignore the error
}
resultBuilder.close();
res = trx.finish(res);
@ -409,7 +462,8 @@ bool RestEdgesHandler::readEdgesForMultipleVertices() {
resultBuilder.close();
// and generate a response
generateResult(HttpResponse::HttpResponseCode::OK, resultBuilder.slice());
generateResult(HttpResponse::HttpResponseCode::OK, resultBuilder.slice(),
trx.transactionContext());
return true;
}

View File

@ -74,6 +74,16 @@ class RestEdgesHandler : public RestVocbaseBaseHandler {
std::vector<traverser::TraverserExpression*> const& expressions,
TRI_edge_direction_e direction, SingleCollectionTransaction& trx,
arangodb::velocypack::Builder&, size_t& scannedIndex, size_t& filtered);
//////////////////////////////////////////////////////////////////////////////
/// @brief get all edges for a list of vertices. Independent from the request
//////////////////////////////////////////////////////////////////////////////
bool getEdgesForVertexList(
arangodb::velocypack::Slice const ids,
std::vector<traverser::TraverserExpression*> const& expressions,
TRI_edge_direction_e direction, SingleCollectionTransaction& trx,
arangodb::velocypack::Builder&, size_t& scannedIndex, size_t& filtered);
};
}

View File

@ -199,30 +199,21 @@ ArangoCollection.prototype._indexurl = function () {
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype._edgesQuery = function (vertex, direction) {
// if vertex is a list, iterator and concat
if (vertex instanceof Array) {
var edges = [];
var i;
for (i = 0; i < vertex.length; ++i) {
var e = this._edgesQuery(vertex[i], direction);
edges.push.apply(edges, e);
if (!(vertex instanceof Array)) {
vertex = [vertex];
}
vertex = vertex.map(function (v) {
if (v.hasOwnProperty("_id")) {
return v._id;
}
return edges;
}
if (vertex.hasOwnProperty("_id")) {
vertex = vertex._id;
}
return v;
});
// get the edges
var url = "/_api/edges/" + encodeURIComponent(this.name())
+ "?vertex=" + encodeURIComponent(vertex)
+ (direction ? "&direction=" + direction : "");
+ (direction ? "?direction=" + direction : "");
var requestResult = this._database._connection.GET(this._prefixurl(url));
var requestResult = this._database._connection.POST(this._prefixurl(url), JSON.stringify(vertex));
arangosh.checkRequestResult(requestResult);