Reputation: 1558
I understand how to write to CSV using [clojure.data.csv]
But I am at a loss as to write the CSV in this specific format.
The data I want to write to CSV is the result of a DB query using [clojure.java.jdbc]
with the as-arrays? true
modifier which returns a 2D array where [0][1]
is the column names
which need to become the headers
in the CSV and then [x][y]
will become the data to write to these headers so [1][0]
will write the first returned row and column 0 to the CSV under the first heading.
(with-open [out-file (io/writer "out-file.csv")]
(csv/write-csv out-file
[["abc" "def"]
["ghi" "jkl"]]))
The above is an example of writing to CSV file, but I am unsure how to use the result of my query and write the values to CSV.
The data will look like this:
[[header1, header2, header3]
[val1, val2, val3]
[val1, val2, val3]]
The query looks like this:
(j/query db ["$SOME_QUERY"] as-arrays? true))
Can somebody help with this?
Edit: update this is what i have so far:
(defn write-query-to-csv [query db output-filename]
(log/info (str "Executing " query " on " db))
(let [results (j/query db ["$QUERY"]
:as-arrays? true)
header (->> results
first)
data (->> results)]
(with-open [out-file (io/writer output-filename)]
(csv/write-csv out-file
(reduce conj (conj [] header) data)))
(io/file output-filename)))
The header data is correct but I'm unsure how to populate the data variabale :/
Upvotes: 0
Views: 388
Reputation: 8854
It looks to me like results
is a sequence of sequences, and in the let
you pull the header sequence out, but don't strip it off of the data. Then header
contains a sequence of header labels, and data
contains the header sequence plus the data sequences (one sequence for each row). The reduce
line adds the header sequence back on to the sequence of sequences--which now contains two header sequences. Most of that isn't necessary. Since results
is in the correct format for passing to write-csv
, the let
only needs to bind results
, and then you can pass results
with no modification as the second argument to write-csv
, like this:
(defn write-query-to-csv [query db output-filename]
(log/info (str "Executing " query " on " db))
(let [results (j/query db ["$QUERY"]
:as-arrays? true)]
(with-open [out-file (io/writer output-filename)]
(csv/write-csv out-file result)
(io/file output-filename)))
So you don't need the reduce
line here, but for future reference, it would probably clearer to replace (conj [] header)
with (vector header)
. Also, another way to write the entire reduce
expression would be (cons header data)
. That will return a different kind of sequence than your reduce
line, but write-csv
won't care, and I think performance should be similar. You could also use (into (vector header) data)
.
Upvotes: 1