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