Redirigir la salida de la consulta mongo a un archivo csv

85

Estoy usando MongoDB 2.2.2 para una máquina Windows7 de 32 bits. Tengo una consulta de agregación compleja en un archivo .js. Necesito ejecutar este archivo en el shell y dirigir la salida a un archivo CSV. Me aseguro de que la consulta devuelva un json "plano" (sin claves anidadas), por lo que es inherentemente convertible a un csv ordenado.

Conozco load()y eval(). eval()requiere que pegue toda la consulta en el shell y solo permite printjson()dentro del script, mientras que necesito csv. Y, la segunda forma: load().. Imprime la salida en la pantalla, y nuevamente en formato json.

¿Hay alguna forma de que Mongo pueda hacer esta conversión de json a csv? (Necesito un archivo csv para preparar gráficos sobre los datos). Estoy pensando:

1. Cualquiera de los dos mongo tiene un comando incorporado para esto que no puedo encontrar en este momento.
2. Mongo no puede hacerlo por mí; Como máximo, puedo enviar la salida json a un archivo que luego necesito convertir a csv yo mismo.
3. Mongo puede enviar la salida json a una colección temporal, cuyo contenido puede ser fácilmente mongoexporteden formato csv. Pero creo que solo las consultas de reducción de mapas admiten colecciones de salida. ¿Está bien? Lo necesito para una consulta de agregación.

Gracias por cualquier ayuda :)

Aafreen Sheikh
fuente
1
Si esto es algo que hace con frecuencia, podría considerar escribir un EXE independiente usando .NET, python, o podría usar NodeJs; cada uno tiene un controlador nativo que facilitaría la ejecución de su código y produciría la salida deseada.
WiredPrairie
Me refiero a la respuesta de Zachary en stackoverflow.com/questions/4130849/… y puedo convertir de json a csv. Pero como alternativa, ¿puedo enviar el json a una colección y luego hacer un mongoexport?
Aafreen Sheikh
Te recomiendo que crees un pequeño arnés usando Node y el controlador MongoDB para NodeJS y luego puedes ejecutar el código que quieras. Obtendría los resultados que desea muy rápidamente sin necesidad de utilizar el caparazón. Sería muy fácil de mantener (y depurar).
WiredPrairie

Respuestas:

175

Sé que esta pregunta es antigua, pero paso una hora tratando de exportar una consulta compleja a csv y quería compartir mis pensamientos. Primero no pude hacer que ninguno de los convertidores json a csv funcionara (aunque este parecía prometedor). Lo que terminé haciendo fue escribir manualmente el archivo csv en mi script mongo.

Esta es una versión simple pero esencialmente lo que hice:

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

Esto acabo de enviar la consulta a stdout

mongo test export.js > out.csv

donde testestá el nombre de la base de datos que utilizo.

GEverding
fuente
¿Cómo puedo especificar en qué base de datos se encuentra la colección de usuarios?
Nelu
2
@NeluMalancea echa un vistazo a los documentos de MongoDB que tienen esta información. Puede especificar la base de datos agregando use <database>en la parte superior del script
GEverding
2
En realidad, dado que los ayudantes de shell como "use <database>" no son javascript, no están permitidos. Consulte docs.mongodb.org/manual/tutorial/… . En su lugar, inicie su secuencia de comandos de esta manera: conn = new Mongo (); db = conn.getDB ('su_db_name');
Steve Hansen Smythe
2
@NeluMalancea el comando mongo acepta una URL de base de datos (y usuario, pase,…)
iwein
3
@NeluMalancea testen el último comando está el nombre de la base de datos, simplemente reemplácelo con el nombre de su base de datos.
Zoltán
112

La exportación incorporada de Mongo funciona bien, a menos que desee manipular datos como fecha de formato, tipos de datos encubiertos, etc.

Seguir el comando funciona como un encanto.

    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
fuente
17
¡Gracias una tonelada! Pista: ahora es en --type=csvlugar de --csv.
Ene
La limitación de mongoexport es que no puede manipular los campos. El ID de mongo se exporta como ObjectId (mongidstring). Ser capaz de exportar los resultados de un script de shell de mongo es mejor si alguien quiere manipular los datos de los campos (por ejemplo, ObjectId (mongidstring) .toString ()).
Raj006
¿Puedo hacer operaciones de agregación?
Hendy Irawan
Esta solución funcionó. Pero para Windows tuve que hacer dos enmiendas: solo necesitaba un apóstrofo doble desde afuera y apóstrofos simples adentro como este -q "{nombre: 'stackoverflow'}", también para especificar el puerto, el comando -p no funcionó, usé - -port 27000.
nurb
10

Ampliando otras respuestas:

Encontré la respuesta de @ GEverding más flexible. También funciona con agregación:

test_db.js

print("name,email");

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

Ejecute el siguiente comando para exportar resultados:

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

Desafortunadamente, agrega texto adicional al archivo CSV que requiere procesar el archivo antes de que podamos usarlo:

MongoDB shell version: 3.2.10 
connecting to: test_db

Pero podemos hacer que mongo shell deje de escupir esos comentarios y solo imprima lo que hemos pedido pasando la --quietbandera

mongo --quiet test_db < ./test_db.js >> ./test_db.csv
Suerte Soni
fuente
1
Editar su respuesta sería mejor que agregar una nueva.
Renato Back
6

Esto es lo que puede probar:

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

}

Guárdelo en un archivo, diga "export.js". Ejecute el siguiente comando:

mongo <host>/<dbname> -u <username> -p <password> export.js > out.csv
Shirish Kumar
fuente
5

Echa un vistazo a esto

para la salida de mongo shell a archivo. No hay soporte para la salida de csv desde mongos shell. Tendría que escribir el javascript usted mismo o usar uno de los muchos convertidores disponibles. Google "convierte json a csv", por ejemplo.

geakie
fuente
0

Solo pesando aquí con una buena solución que he estado usando. Esto es similar a la solución de Lucky Soni anterior, ya que admite la agregación, pero no requiere la codificación de los nombres de los campos.

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);
}

Guarde esto como un .jsarchivo, en este caso lo llamaremos example.jsy lo ejecutaremos con la línea de comando mongo así:

mongo <database_name> example.js --quiet > example.csv
TimmyGee
fuente