diff --git a/arangosh/Export/ExportFeature.cpp b/arangosh/Export/ExportFeature.cpp index e6766be0e1..2b188d45c8 100644 --- a/arangosh/Export/ExportFeature.cpp +++ b/arangosh/Export/ExportFeature.cpp @@ -317,7 +317,8 @@ std::shared_ptr ExportFeature::httpCall(SimpleHttpClient* httpClie if (response->wasHttpError()) { if (response->getHttpReturnCode() == 404) { - LOG(FATAL) << "Collection not found."; + LOG(FATAL) << "Collection or graph not found."; + FATAL_ERROR_EXIT(); } else { parsedBody = response->getBodyVelocyPack(); std::cout << parsedBody->toJson() << std::endl; @@ -352,16 +353,33 @@ void ExportFeature::graphExport(SimpleHttpClient* httpClient) { std::string errorMsg; - // filename is immer graphname + if (_collections.empty()) { + std::cout << "export graph '" << _graphName << "'" << std::endl; + std::string const url = "/_api/gharial/" + _graphName; + std::shared_ptr parsedBody = httpCall(httpClient, url, rest::RequestType::GET); + VPackSlice body = parsedBody->slice(); - // if collections yeah - // graphname only -> get all collection for the graph - + std::unordered_set collections; + for(auto const& edgeDefs : VPackArrayIterator(body.get("graph").get("edgeDefinitions"))) { + collections.insert(edgeDefs.get("collection").copyString()); + for(auto const& from : VPackArrayIterator(edgeDefs.get("from"))) { + collections.insert(from.copyString()); + } + for(auto const& to : VPackArrayIterator(edgeDefs.get("to"))) { + collections.insert(to.copyString()); + } + } + for (auto const& cn : collections) { + _collections.push_back(cn); + } + } else { + std::cout << "export graph with collections " << StringUtils::join(_collections, ", ") << " as '" << _graphName << "'" << std::endl; + } std::string fileName = _outputDirectory + TRI_DIR_SEPARATOR_STR + _graphName + "." + _typeExport; @@ -378,11 +396,64 @@ void ExportFeature::graphExport(SimpleHttpClient* httpClient) { } TRI_DEFER(TRI_CLOSE(fd)); + std::string xmlHeader = R"( + +)"; + writeToFile(fd, xmlHeader, fileName); + for (auto const& collection : _collections) { + if (_progress) { + std::cout << "# Exporting collection '" << collection << "'..." << std::endl; + } + std::string const url = "_api/cursor"; + VPackBuilder post; + post.openObject(); + post.add("query", VPackValue("FOR doc IN @@collection RETURN doc")); + post.add("bindVars", VPackValue(VPackValueType::Object)); + post.add("@collection", VPackValue(collection)); + post.close(); + post.close(); + std::shared_ptr parsedBody = httpCall(httpClient, url, rest::RequestType::POST, post.toJson()); + VPackSlice body = parsedBody->slice(); + writeGraphBatch(fd, VPackArrayIterator(body.get("result")), fileName); + while (body.hasKey("id")) { + std::string const url = "/_api/cursor/"+body.get("id").copyString(); + parsedBody = httpCall(httpClient, url, rest::RequestType::PUT); + body = parsedBody->slice(); + + writeGraphBatch(fd, VPackArrayIterator(body.get("result")), fileName); + } + } + std::string closingGraphTag = "\n"; + writeToFile(fd, closingGraphTag, fileName); +} + +void ExportFeature::writeGraphBatch(int fd, VPackArrayIterator it, std::string const& fileName) { + + // todos: + // insert actual label, options to have also attributes + for(auto const& doc : it) { + if (doc.hasKey("_from")) { + // + std::string edge = "\n"; + writeToFile(fd, edge, fileName); + + } else { + // + std::string node = "\n"; + writeToFile(fd, node, fileName); + } + } } diff --git a/arangosh/Export/ExportFeature.h b/arangosh/Export/ExportFeature.h index 4dd82cbcba..0bbbd843da 100644 --- a/arangosh/Export/ExportFeature.h +++ b/arangosh/Export/ExportFeature.h @@ -53,6 +53,7 @@ class ExportFeature final : public application_features::ApplicationFeature, void collectionExport(httpclient::SimpleHttpClient* httpClient); void writeCollectionBatch(int fd, VPackArrayIterator it, std::string const& fileName); void graphExport(httpclient::SimpleHttpClient* httpClient); + void writeGraphBatch(int fd, VPackArrayIterator it, std::string const& fileName); void writeToFile(int fd, std::string& string, std::string const& fileName); std::shared_ptr httpCall(httpclient::SimpleHttpClient* httpClient, std::string const& url, arangodb::rest::RequestType, std::string postBody = "");