mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of https://github.com/arangodb/arangodb into engine-api
This commit is contained in:
commit
a420093f2d
|
@ -50,6 +50,16 @@ Export JSONL
|
||||||
|
|
||||||
This exports the collection *test* into the output directory *export* as [jsonl](http://jsonlines.org). Every line in the export is one document from the collection *test* as json.
|
This exports the collection *test* into the output directory *export* as [jsonl](http://jsonlines.org). Every line in the export is one document from the collection *test* as json.
|
||||||
|
|
||||||
|
Export CSV
|
||||||
|
----------
|
||||||
|
|
||||||
|
unix> arangoexport --type CSV --collection test --fields _key,_id,_rev
|
||||||
|
|
||||||
|
This exports the collection *test* into the output directory *export* as CSV. The first
|
||||||
|
line contains the header with all field names. Each line is one document represented as
|
||||||
|
CSV and separated with a comma. Objects and Arrays are represented as a JSON string.
|
||||||
|
|
||||||
|
|
||||||
Export XML
|
Export XML
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|
|
@ -1252,10 +1252,8 @@ void AgencyComm::updateEndpoints(arangodb::velocypack::Slice const& current) {
|
||||||
<< "Removing endpoint " << i << " from agent pool";
|
<< "Removing endpoint " << i << " from agent pool";
|
||||||
AgencyCommManager::MANAGER->removeEndpoint(i);
|
AgencyCommManager::MANAGER->removeEndpoint(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AgencyCommResult AgencyComm::sendWithFailover(
|
AgencyCommResult AgencyComm::sendWithFailover(
|
||||||
arangodb::rest::RequestType method, double const timeout,
|
arangodb::rest::RequestType method, double const timeout,
|
||||||
std::string const& initialUrl, std::string const& body,
|
std::string const& initialUrl, std::string const& body,
|
||||||
|
@ -1400,11 +1398,6 @@ AgencyCommResult AgencyComm::sendWithFailover(
|
||||||
"Inquiry failed (" << inq._statusCode << "). Keep trying ...";
|
"Inquiry failed (" << inq._statusCode << "). Keep trying ...";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
AgencyCommManager::MANAGER->failed(std::move(connection), endpoint);
|
|
||||||
endpoint.clear();
|
|
||||||
connection = AgencyCommManager::MANAGER->acquire(endpoint);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sometimes the agency will return a 307 (temporary redirect)
|
// sometimes the agency will return a 307 (temporary redirect)
|
||||||
|
|
|
@ -99,9 +99,8 @@ AstNode* EdgeConditionBuilder::getInboundCondition() {
|
||||||
EdgeConditionBuilderContainer::EdgeConditionBuilderContainer() :
|
EdgeConditionBuilderContainer::EdgeConditionBuilderContainer() :
|
||||||
EdgeConditionBuilder(nullptr) {
|
EdgeConditionBuilder(nullptr) {
|
||||||
auto node = std::make_unique<AstNode>(NODE_TYPE_OPERATOR_NARY_AND);
|
auto node = std::make_unique<AstNode>(NODE_TYPE_OPERATOR_NARY_AND);
|
||||||
_modCondition = node.get();
|
|
||||||
_astNodes.emplace_back(node.get());
|
_astNodes.emplace_back(node.get());
|
||||||
node.release();
|
_modCondition = node.release();
|
||||||
|
|
||||||
auto comp = std::make_unique<AstNode>(NODE_TYPE_VALUE);
|
auto comp = std::make_unique<AstNode>(NODE_TYPE_VALUE);
|
||||||
comp->setValueType(VALUE_TYPE_STRING);
|
comp->setValueType(VALUE_TYPE_STRING);
|
||||||
|
|
|
@ -35,6 +35,9 @@ class Scheduler;
|
||||||
|
|
||||||
class JobGuard {
|
class JobGuard {
|
||||||
public:
|
public:
|
||||||
|
JobGuard(JobGuard const&) = delete;
|
||||||
|
JobGuard& operator=(JobGuard const&) = delete;
|
||||||
|
|
||||||
explicit JobGuard(EventLoop const& loop) : _scheduler(loop._scheduler) {}
|
explicit JobGuard(EventLoop const& loop) : _scheduler(loop._scheduler) {}
|
||||||
explicit JobGuard(rest::Scheduler* scheduler) : _scheduler(scheduler) {}
|
explicit JobGuard(rest::Scheduler* scheduler) : _scheduler(scheduler) {}
|
||||||
~JobGuard() { release(); }
|
~JobGuard() { release(); }
|
||||||
|
@ -43,6 +46,8 @@ class JobGuard {
|
||||||
bool isIdle() { return _scheduler->isIdle(); }
|
bool isIdle() { return _scheduler->isIdle(); }
|
||||||
|
|
||||||
void work() {
|
void work() {
|
||||||
|
TRI_ASSERT(!_isWorkingFlag);
|
||||||
|
|
||||||
if (0 == _isWorking) {
|
if (0 == _isWorking) {
|
||||||
_scheduler->workThread();
|
_scheduler->workThread();
|
||||||
}
|
}
|
||||||
|
@ -52,6 +57,8 @@ class JobGuard {
|
||||||
}
|
}
|
||||||
|
|
||||||
void block() {
|
void block() {
|
||||||
|
TRI_ASSERT(!_isBlockedFlag);
|
||||||
|
|
||||||
if (0 == _isBlocked) {
|
if (0 == _isBlocked) {
|
||||||
_scheduler->blockThread();
|
_scheduler->blockThread();
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,9 @@
|
||||||
#include "SimpleHttpClient/SimpleHttpClient.h"
|
#include "SimpleHttpClient/SimpleHttpClient.h"
|
||||||
#include "SimpleHttpClient/SimpleHttpResult.h"
|
#include "SimpleHttpClient/SimpleHttpResult.h"
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
#include <boost/property_tree/detail/xml_parser_utils.hpp>
|
#include <boost/property_tree/detail/xml_parser_utils.hpp>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::basics;
|
using namespace arangodb::basics;
|
||||||
|
@ -47,6 +49,8 @@ ExportFeature::ExportFeature(application_features::ApplicationServer* server,
|
||||||
_graphName(),
|
_graphName(),
|
||||||
_xgmmlLabelAttribute("label"),
|
_xgmmlLabelAttribute("label"),
|
||||||
_typeExport("json"),
|
_typeExport("json"),
|
||||||
|
_csvFieldOptions(),
|
||||||
|
_csvFields(),
|
||||||
_xgmmlLabelOnly(false),
|
_xgmmlLabelOnly(false),
|
||||||
_outputDirectory(),
|
_outputDirectory(),
|
||||||
_overwrite(false),
|
_overwrite(false),
|
||||||
|
@ -92,7 +96,10 @@ void ExportFeature::collectOptions(
|
||||||
options->addOption("--progress", "show progress",
|
options->addOption("--progress", "show progress",
|
||||||
new BooleanParameter(&_progress));
|
new BooleanParameter(&_progress));
|
||||||
|
|
||||||
std::unordered_set<std::string> exports = {"json", "jsonl", "xgmml", "xml"};
|
options->addOption("--fields", "comma separated list of fileds to export into a csv file",
|
||||||
|
new StringParameter(&_csvFieldOptions));
|
||||||
|
|
||||||
|
std::unordered_set<std::string> exports = {"csv", "json", "jsonl", "xgmml", "xml"};
|
||||||
options->addOption(
|
options->addOption(
|
||||||
"--type", "type of export", new DiscreteValuesParameter<StringParameter>(&_typeExport, exports));
|
"--type", "type of export", new DiscreteValuesParameter<StringParameter>(&_typeExport, exports));
|
||||||
}
|
}
|
||||||
|
@ -127,6 +134,21 @@ void ExportFeature::validateOptions(
|
||||||
LOG_TOPIC(FATAL, Logger::CONFIG) << "expecting a graph name to dump a graph";
|
LOG_TOPIC(FATAL, Logger::CONFIG) << "expecting a graph name to dump a graph";
|
||||||
FATAL_ERROR_EXIT();
|
FATAL_ERROR_EXIT();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( (_typeExport == "json" || _typeExport == "jsonl" || _typeExport == "csv") &&
|
||||||
|
_collections.empty()) {
|
||||||
|
LOG_TOPIC(FATAL, Logger::CONFIG) << "expecting at least one collection";
|
||||||
|
FATAL_ERROR_EXIT();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_typeExport == "csv") {
|
||||||
|
if (_csvFieldOptions.empty()) {
|
||||||
|
LOG_TOPIC(FATAL, Logger::CONFIG) << "expecting at least one field definition";
|
||||||
|
FATAL_ERROR_EXIT();
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::split(_csvFields, _csvFieldOptions, boost::is_any_of(","));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportFeature::prepare() {
|
void ExportFeature::prepare() {
|
||||||
|
@ -209,7 +231,7 @@ void ExportFeature::start() {
|
||||||
|
|
||||||
uint64_t exportedSize = 0;
|
uint64_t exportedSize = 0;
|
||||||
|
|
||||||
if (_typeExport == "json" || _typeExport == "jsonl" || _typeExport == "xml") {
|
if (_typeExport == "json" || _typeExport == "jsonl" || _typeExport == "xml" || _typeExport == "csv") {
|
||||||
if (_collections.size()) {
|
if (_collections.size()) {
|
||||||
collectionExport(httpClient.get());
|
collectionExport(httpClient.get());
|
||||||
|
|
||||||
|
@ -282,12 +304,27 @@ void ExportFeature::collectionExport(SimpleHttpClient* httpClient) {
|
||||||
if (_typeExport == "json") {
|
if (_typeExport == "json") {
|
||||||
std::string openingBracket = "[";
|
std::string openingBracket = "[";
|
||||||
writeToFile(fd, openingBracket, fileName);
|
writeToFile(fd, openingBracket, fileName);
|
||||||
|
|
||||||
} else if (_typeExport == "xml") {
|
} else if (_typeExport == "xml") {
|
||||||
std::string xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
|
std::string xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
|
||||||
"<collection name=\"";
|
"<collection name=\"";
|
||||||
xmlHeader.append(encode_char_entities(collection));
|
xmlHeader.append(encode_char_entities(collection));
|
||||||
xmlHeader.append("\">\n");
|
xmlHeader.append("\">\n");
|
||||||
writeToFile(fd, xmlHeader, fileName);
|
writeToFile(fd, xmlHeader, fileName);
|
||||||
|
|
||||||
|
} else if (_typeExport == "csv") {
|
||||||
|
std::string firstLine = "";
|
||||||
|
bool isFirstValue = true;
|
||||||
|
for(auto const& str : _csvFields) {
|
||||||
|
if (isFirstValue) {
|
||||||
|
firstLine += str;
|
||||||
|
isFirstValue = false;
|
||||||
|
} else {
|
||||||
|
firstLine += "," + str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
firstLine += "\n";
|
||||||
|
writeToFile(fd, firstLine, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeCollectionBatch(fd, VPackArrayIterator(body.get("result")), fileName);
|
writeCollectionBatch(fd, VPackArrayIterator(body.get("result")), fileName);
|
||||||
|
@ -333,6 +370,41 @@ void ExportFeature::writeCollectionBatch(int fd, VPackArrayIterator it, std::str
|
||||||
line += doc.toJson();
|
line += doc.toJson();
|
||||||
writeToFile(fd, line, fileName);
|
writeToFile(fd, line, fileName);
|
||||||
}
|
}
|
||||||
|
} else if (_typeExport == "csv") {
|
||||||
|
for (auto const& doc : it) {
|
||||||
|
line.clear();
|
||||||
|
bool isFirstValue = true;
|
||||||
|
|
||||||
|
for(auto const& key : _csvFields) {
|
||||||
|
std::string value = "";
|
||||||
|
|
||||||
|
if (isFirstValue) {
|
||||||
|
isFirstValue = false;
|
||||||
|
} else {
|
||||||
|
line.append(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc.hasKey(key)) {
|
||||||
|
VPackSlice val = doc.get(key);
|
||||||
|
|
||||||
|
if (val.isArray() || val.isObject()) {
|
||||||
|
value = val.toJson();
|
||||||
|
} else {
|
||||||
|
if (val.isString()) {
|
||||||
|
value = val.copyString();
|
||||||
|
} else {
|
||||||
|
value = val.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value = std::regex_replace(value, std::regex("\""), "\"\"");
|
||||||
|
value = std::regex_replace(value, std::regex(","), "\",");
|
||||||
|
}
|
||||||
|
line.append(value);
|
||||||
|
}
|
||||||
|
line.append("\n");
|
||||||
|
writeToFile(fd, line, fileName);
|
||||||
|
}
|
||||||
} else if (_typeExport == "xml") {
|
} else if (_typeExport == "xml") {
|
||||||
for (auto const& doc : it) {
|
for (auto const& doc : it) {
|
||||||
line.clear();
|
line.clear();
|
||||||
|
|
|
@ -64,6 +64,8 @@ class ExportFeature final : public application_features::ApplicationFeature,
|
||||||
std::string _graphName;
|
std::string _graphName;
|
||||||
std::string _xgmmlLabelAttribute;
|
std::string _xgmmlLabelAttribute;
|
||||||
std::string _typeExport;
|
std::string _typeExport;
|
||||||
|
std::string _csvFieldOptions;
|
||||||
|
std::vector<std::string> _csvFields;
|
||||||
bool _xgmmlLabelOnly;
|
bool _xgmmlLabelOnly;
|
||||||
|
|
||||||
std::string _outputDirectory;
|
std::string _outputDirectory;
|
||||||
|
|
Loading…
Reference in New Issue