diff options
Diffstat (limited to 'tools/export.cpp')
-rw-r--r-- | tools/export.cpp | 69 |
1 files changed, 44 insertions, 25 deletions
diff --git a/tools/export.cpp b/tools/export.cpp index 5603823..0262c4b 100644 --- a/tools/export.cpp +++ b/tools/export.cpp @@ -33,34 +33,34 @@ namespace po = boost::program_options; class Export : public Tool { public: - Export() : Tool( "export" ){ + Export() : Tool( "export" ) { addFieldOptions(); add_options() - ("query,q" , po::value<string>() , "query filter, as a JSON string" ) - ("csv","export to csv instead of json") - ("out,o", po::value<string>(), "output file; if not specified, stdout is used") - ("jsonArray", "output to a json array rather than one object per line") - ; + ("query,q" , po::value<string>() , "query filter, as a JSON string" ) + ("csv","export to csv instead of json") + ("out,o", po::value<string>(), "output file; if not specified, stdout is used") + ("jsonArray", "output to a json array rather than one object per line") + ; _usesstdout = false; } - - int run(){ + + int run() { string ns; const bool csv = hasParam( "csv" ); const bool jsonArray = hasParam( "jsonArray" ); ostream *outPtr = &cout; string outfile = getParam( "out" ); auto_ptr<ofstream> fileStream; - if ( hasParam( "out" ) ){ + if ( hasParam( "out" ) ) { size_t idx = outfile.rfind( "/" ); - if ( idx != string::npos ){ + if ( idx != string::npos ) { string dir = outfile.substr( 0 , idx + 1 ); create_directories( dir ); } ofstream * s = new ofstream( outfile.c_str() , ios_base::out ); fileStream.reset( s ); outPtr = s; - if ( ! s->good() ){ + if ( ! s->good() ) { cerr << "couldn't open [" << outfile << "]" << endl; return -1; } @@ -72,36 +72,55 @@ public: try { ns = getNS(); - } catch (...) { + } + catch (...) { printHelp(cerr); return 1; } auth(); - if ( hasParam( "fields" ) || csv ){ + if ( hasParam( "fields" ) || csv ) { needFields(); - fieldsToReturn = &_fieldsObj; + + // we can't use just _fieldsObj since we support everything getFieldDotted does + + set<string> seen; + BSONObjBuilder b; + + BSONObjIterator i( _fieldsObj ); + while ( i.more() ){ + BSONElement e = i.next(); + string f = str::before( e.fieldName() , '.' ); + if ( seen.insert( f ).second ) + b.append( f , 1 ); + } + + realFieldsToReturn = b.obj(); + fieldsToReturn = &realFieldsToReturn; } - - - if ( csv && _fields.size() == 0 ){ + + + if ( csv && _fields.size() == 0 ) { cerr << "csv mode requires a field list" << endl; return -1; } + Query q( getParam( "query" , "" ) ); + if ( q.getFilter().isEmpty() && !hasParam("dbpath")) + q.snapshot(); - auto_ptr<DBClientCursor> cursor = conn().query( ns.c_str() , ((Query)(getParam( "query" , "" ))).snapshot() , 0 , 0 , fieldsToReturn , QueryOption_SlaveOk | QueryOption_NoCursorTimeout ); + auto_ptr<DBClientCursor> cursor = conn().query( ns.c_str() , q , 0 , 0 , fieldsToReturn , QueryOption_SlaveOk | QueryOption_NoCursorTimeout ); - if ( csv ){ - for ( vector<string>::iterator i=_fields.begin(); i != _fields.end(); i++ ){ + if ( csv ) { + for ( vector<string>::iterator i=_fields.begin(); i != _fields.end(); i++ ) { if ( i != _fields.begin() ) out << ","; out << *i; } out << endl; } - + if (jsonArray) out << '['; @@ -109,12 +128,12 @@ public: while ( cursor->more() ) { num++; BSONObj obj = cursor->next(); - if ( csv ){ - for ( vector<string>::iterator i=_fields.begin(); i != _fields.end(); i++ ){ + if ( csv ) { + for ( vector<string>::iterator i=_fields.begin(); i != _fields.end(); i++ ) { if ( i != _fields.begin() ) out << ","; const BSONElement & e = obj.getFieldDotted(i->c_str()); - if ( ! e.eoo() ){ + if ( ! e.eoo() ) { out << e.jsonString( Strict , false ); } } @@ -133,7 +152,7 @@ public: if (jsonArray) out << ']' << endl; - + cerr << "exported " << num << " records" << endl; return 0; |