2

I was looking at this thread: mongoexport aggregate export to a csv file

and I was able to use the suggested .toCsv() with db.collection.find() but I am unable to use it with db.collection.aggregate().toCsv()

It gives me an error:

TypeError: ...toCsv() is not a function. Details: $(shell):1:1

What am I doing wrong?

Ravi Shankar Bharti
  • 8,922
  • 5
  • 28
  • 52
Ivo Hristov
  • 83
  • 1
  • 5
  • fwiw, the second answer to that question (using $out) seems like a better approach. (I think the first answer was written before mongo 2.6 added $out) – klhr Jul 01 '19 at 20:32

2 Answers2

1

The script that you're using is monkey-patching DBCommandCursor.prototype.toCsv to add the toCsv method to cursors, and it seems like that doesn't work for aggregation cursors for some reason (and doesn't work at all on the version of mongo I'm running).

Rather than figuring out why the mongo shell isn't behaving the way that you'd like, one dangerous approach would be to instead monkey-patch the Array.prototype

Array.prototype.toCSV = function toMediocreCSV () {
  const results = this;
  const headers = {};
  results.forEach((result) =>
    Object.keys(result).forEach((key) => headers[key] = true)
  )
  const keys = Object.keys(headers);
  print(keys.join(","));
  results.forEach((result) =>
    print(keys.map((key) => result[key] != null ? result[key] : '')
      .join(",")) 
  )
}
> db.test.aggregate().toArray().toCSV()
_id,a,b,c
ObjectId("5d1a77e1688b8f1d66098375"),1,2,
ObjectId("5d1a77e1688b8f1d66098376"),3,,4

Alternatively, you could write a similar function that takes in an array and formats it the way that you'd like: the only benefit to modifying the prototype would be the ability to chain things nicely.

klhr
  • 3,300
  • 1
  • 11
  • 25
  • I have modified your code to accommodate for a textQualifier. Otherwise, it messes with the columns if there is a key with array. `Array.prototype.toCSV = function toMediocreCSV () { const results = this; const headers = {}; results.forEach((result) => Object.keys(result).forEach((key) => headers[key] = true) ) const keys = Object.keys(headers); print("\'"+keys.join("\',\'")+"\'"); results.forEach((result) => print("\'"+keys.map((key) => result[key] != null ? result[key] : '') .join("\',\'")+"\'") ) };` – Ivo Hristov Jul 02 '19 at 10:07
0

Hey there the mongo command is telling you that toCVS

the solution I prefer is the following

var result = db.compras.aggregate()

then you put your result into a collection

db.agr.insert(result.result);

the use mongoexport

mongoexport -d yourdbname -c agr -f _id,total --csv > results.csv
Balint
  • 295
  • 2
  • 11
  • This seems a very complicated approach considering that I have to modify my aggregation, add to a collection, mongoexport it, search for the exported file, etc. instead I could just add .toCsv() at the end and the results are ready for copy/paste in Excel. I am using this sort of exports a lot in my work and using mongoexport is very time consuming for me. – Ivo Hristov Jul 01 '19 at 12:43