Skill 05 · Clickhouse Js Node Coding
Subchapter 5.11
reference/select-formats.mdMarkdown7 KBView on GitHub
Applies to: all versions.
JSONEachRowWithProgressrequires client>= 1.7.0; see the in-repo performance examples underexamples/node/performance/.
Right answer for ~90% of selects when the result fits in memory.
import { createClient } from "@clickhouse/client";
interface Row {
number: string;
}
const client = createClient();
const rows = await client.query({
query: "SELECT number FROM system.numbers LIMIT 5",
format: "JSONEachRow",
});
const result = await rows.json<Row>(); // Row[]
result.forEach((r) => console.log(r));
// { number: '0' }
// { number: '1' }
// ...
await client.close();UInt64/Int64 and other 64-bit integers are returned as strings
when output_format_json_quote_64bit_integers=1, to avoid JS precision
loss. If that setting is 0, they may be returned as unquoted JSON
numbers instead. Note that in ClickHouse >= 25.8, this setting can
default to 0; see the troubleshooting skill for ways to control that.
Use JSON (or JSONCompact) when you need ClickHouse’s response envelope
(rows + meta + statistics + row count). Type the result with
ResponseJSON<T>:
import { createClient, type ResponseJSON } from "@clickhouse/client";
const client = createClient();
const rows = await client.query({
query: "SELECT number FROM system.numbers LIMIT 2",
format: "JSON",
});
const result = await rows.json<ResponseJSON<{ number: string }>>();
console.info(result.meta, result.data, result.rows, result.statistics);
await client.close();
JSON,JSONCompact,JSONStrings,JSONCompactStrings,JSONColumnsWithMetadata,JSONObjectEachRoware single-document formats — they cannot be streamed. Use a*EachRowvariant if you want to stream.
Use .text() (not .json()) for raw textual formats:
const rs = await client.query({
query: "SELECT number, number * 2 AS doubled FROM system.numbers LIMIT 3",
format: "CSVWithNames",
});
console.log(await rs.text());Streaming raw text/Parquet line-by-line belongs in
examples/node/performance/ (opens in a new tab)
— in particular, Parquet exports use client.exec() and pipe the raw
response stream rather than ResultSet.stream() (see
select_parquet_as_file.ts (opens in a new tab)).
| Use case | Format |
|---|---|
| Read rows as JS objects | JSONEachRow (default) |
| Read rows as positional tuples (smaller payload) | JSONCompactEachRow |
Need meta / statistics / rows envelope | JSON or JSONCompact + ResponseJSON<T> |
| Read all values as strings (avoid number-precision loss) | JSONStringsEachRow / JSONCompactStringsEachRow |
| Stream very large result | JSONEachRow / JSONCompactEachRow (see examples/node/performance/ (opens in a new tab)) |
| Export to CSV/TSV/Parquet | CSV*, TabSeparated*, Parquet (see examples/node/performance/ (opens in a new tab)) |
| Method | Returns | Notes |
|---|---|---|
await rs.json<T>() | T[] for *EachRow, single-doc shape otherwise | Buffers the full response |
await rs.text() | string | Buffers the full response — for textual formats only (CSV/TSV/etc.) |
rs.stream() | Node Readable of Row[] chunks | Use for large newline-delimited results (JSONEachRow/JSONCompactEachRow/CSV/TSV); not suitable for binary formats like Parquet — for those, use client.exec() and pipe the raw response stream (see examples/node/performance/ (opens in a new tab)) |
rs.close() | void (synchronous) | Always call if you obtained stream() and stop reading early |
.json() on a JSON (single-doc) result and expecting an
array. You get a ResponseJSON<T> object; the rows are under
.data. Use JSONEachRow if you want a flat array.stream() half-consumed. This is a top cause of
ECONNRESET on the next request — fully iterate the stream or call
resultSet.close() (synchronous — no await). (Diagnosis details live in the
troubleshooting skill.).json() on a CSV/TSV result. Use .text() (or
.stream() for large results).