Przekieruj dane wyjściowe zapytania mongo do pliku csv

85

Używam MongoDB 2.2.2 na komputerze z 32-bitowym systemem Windows7. Mam złożone zapytanie agregujące w pliku .js. Muszę wykonać ten plik w powłoce i skierować dane wyjściowe do pliku CSV. Zapewniam, że zapytanie zwraca „płaski” plik JSON (bez zagnieżdżonych kluczy), więc jest z natury konwertowany na schludny plik CSV.

Wiem o load()i eval(). eval()wymaga ode mnie wklejenia całego zapytania do powłoki i pozwala tylko printjson()wewnątrz skryptu, podczas gdy potrzebuję csv. Drugi sposób: load()... Drukuje wynik na ekranie i znowu w formacie json.

Czy istnieje sposób, w jaki Mongo może wykonać tę konwersję z json na csv? (Potrzebuję pliku csv, aby przygotować wykresy na danych). Myślę:

1. Każda mongo ma wbudowane polecenie, którego nie mogę teraz znaleźć.
2. Mongo nie może tego zrobić za mnie; Mogę co najwyżej wysłać dane wyjściowe json do pliku, który następnie muszę sam przekonwertować na csv.
3. Mongo może wysłać dane wyjściowe json do tymczasowej kolekcji, której zawartość można łatwo zapisać mongoexportedw formacie csv. Ale myślę, że tylko zapytania ograniczające mapę obsługują zbiory danych wyjściowych. Czy to prawda? Potrzebuję go do zapytania agregującego.

Dzięki za wszelką pomoc :)

Aafreen Sheikh
źródło
1
Jeśli jest to coś, co często robisz, możesz rozważyć napisanie samodzielnego EXE przy użyciu .NET, pythona lub NodeJs; każdy ma natywny sterownik, który ułatwi wykonanie kodu i wygeneruje żądane dane wyjściowe.
WiredPrairie
Mam na myśli odpowiedź Zachary'ego na stackoverflow.com/questions/4130849/ ... i jestem w stanie przekonwertować z json na csv. Ale alternatywnie, czy mogę wyprowadzić plik json do kolekcji, a następnie wykonać mongoeksport?
Aafreen Sheikh
Radziłbym po prostu zbudować małą wiązkę przewodów za pomocą Node i sterownika MongoDB dla NodeJS, a następnie możesz wykonać dowolny kod. Uzyskasz pożądane wyniki bardzo szybko, bez konieczności posiadania powłoki. Byłoby bardzo łatwe w utrzymaniu (i debugowaniu).
WiredPrairie

Odpowiedzi:

175

Wiem, że to pytanie jest stare, ale spędziłem godzinę próbując wyeksportować złożone zapytanie do csv i chciałem podzielić się swoimi przemyśleniami. Najpierw nie udało mi się uruchomić żadnego z konwerterów json na csv (chociaż ten wyglądał obiecująco). Skończyło się na tym, że ręcznie zapisałem plik csv w moim skrypcie mongo.

To jest prosta wersja, ale zasadniczo to, co zrobiłem:

print("name,id,email");
db.User.find().forEach(function(user){
  print(user.name+","+user._id.valueOf()+","+user.email);
});

To właśnie wysłałem zapytanie do stdout

mongo test export.js > out.csv

gdzie testjest nazwa bazy danych, której używam.

GEverding
źródło
Jak określić, w której bazie danych znajduje się kolekcja User?
Nelu
2
@NeluMalancea sprawdź dokumenty MongoDB, w których mają te informacje. Możesz określić use <database>
bazę
2
Właściwie, ponieważ pomoce powłoki, takie jak "użyj <bazy danych>" nie są javascript, nie są dozwolone. Zobacz docs.mongodb.org/manual/tutorial/… . Zamiast tego uruchom skrypt w ten sposób: conn = new Mongo (); db = conn.getDB ('twoja_nazwa_db');
Steve Hansen Smythe
2
@NeluMalancea polecenie mongo akceptuje adres URL db (i user, pass,…)
iwein
3
@NeluMalancea testw ostatnim poleceniu jest nazwa bazy danych, po prostu zastąp ją nazwą swojej bazy danych.
Zoltán,
112

Wbudowany eksport Mongo działa dobrze, chyba że chcesz manipulować danymi, takimi jak data formatu, ukryte typy danych itp.

Następujące polecenie działa jak urok.

    mongoexport -h localhost -d databse -c collection --type=csv 
    --fields erpNum,orderId,time,status 
    -q '{"time":{"$gt":1438275600000}, "status":{"$ne" :"Cancelled"}}' 
    --out report.csv
thisarattr
źródło
17
Wielkie dzięki! Podpowiedź: teraz jest --type=csvzamiast --csv.
Jan
Ograniczeniem mongoeksportu jest to, że nie możesz manipulować polami. Identyfikator mongo jest eksportowany jako ObjectId (mongidstring). Możliwość eksportowania wyników ze skryptu powłoki mongo jest lepsza, jeśli ktoś chce manipulować danymi pól (na przykład ObjectId (mongidstring) .toString ()).
Raj006
czy mogę wykonywać operacje agregacji?
Hendy Irawan
To rozwiązanie zadziałało. Ale dla Windows musiałem wprowadzić dwie poprawki: potrzebowałem tylko podwójnego apostrofu z zewnątrz i pojedynczych apostrofów wewnątrz, takich jak ten -q "{name: 'stackoverflow'}", również dla określania portu Polecenie -p nie działało, użyłem - -port 27000.
nurb
10

Rozszerzanie innych odpowiedzi:

Uważam, że odpowiedź @ GEverding jest najbardziej elastyczna. Działa również z agregacją:

test_db.js

print("name,email");

db.users.aggregate([
    { $match: {} }
]).forEach(function(user) {
        print(user.name+","+user.email);
    }
});

Wykonaj następujące polecenie, aby wyeksportować wyniki:

mongo test_db < ./test_db.js >> ./test_db.csv

Niestety, dodaje dodatkowy tekst do pliku CSV, który wymaga przetworzenia pliku, zanim będziemy mogli go użyć:

MongoDB shell version: 3.2.10 
connecting to: test_db

Ale możemy sprawić, że skorupa mongo przestanie wypluwać te komentarze i wydrukuje tylko to, o co poprosiliśmy, przekazując --quietflagę

mongo --quiet test_db < ./test_db.js >> ./test_db.csv
Lucky Soni
źródło
1
Edycja jego odpowiedzi byłaby lepsza niż dodanie nowej.
Renato Back
6

Oto, czego możesz spróbować:

print("id,name,startDate")
cursor = db.<collection_name>.find();
while (cursor.hasNext()) {
    jsonObject = cursor.next();
    print(jsonObject._id.valueOf() + "," + jsonObject.name + ",\"" + jsonObject.stateDate.toUTCString() +"\"")

}

Zapisz to w pliku, powiedz „export.js”. Uruchom następujące polecenie:

mongo <host>/<dbname> -u <username> -p <password> export.js > out.csv
Shirish Kumar
źródło
5

Spójrz na to

do wyprowadzania z powłoki mongo do pliku. Nie ma wsparcia dla wypisywania csv z powłoki mongos. Musiałbyś sam napisać javascript lub użyć jednego z wielu dostępnych konwerterów. Na przykład Google „przekonwertuje json na csv”.

geakie
źródło
0

Właśnie tu ważę z ładnym rozwiązaniem, którego używałem. Jest to podobne do rozwiązania Lucky Soni powyżej, ponieważ obsługuje agregację, ale nie wymaga twardego kodowania nazw pól.

cursor = db.<collection_name>.<my_query_with_aggregation>;

headerPrinted = false;
while (cursor.hasNext()) {
    item = cursor.next();
    
    if (!headerPrinted) {
        print(Object.keys(item).join(','));
        headerPrinted = true;
    }

    line = Object
        .keys(item)
        .map(function(prop) {
            return '"' + item[prop] + '"';
        })
        .join(',');
    print(line);
}

Zapisz to jako .jsplik, w tym przypadku nazwiemy go example.jsi uruchomimy z linią poleceń mongo w następujący sposób:

mongo <database_name> example.js --quiet > example.csv
TimmyGee
źródło