demo D231
A hundred thousand rows in DuckDB, no server in Vue
DuckDB reads a Parquet file in the browser and the whole set is pulled in, so the plant subtotals and the grand total are computed over all 100,000 rows
createPushdownSource · duckdbAdapter · fullDataset
This grid reads a Parquet file with DuckDB in the browser and pulls the whole hundred-thousand-row set through it, so the subtotals and grand total are computed over every row. It shows analytical figures that cover the full dataset, with no server involved.
This is the Vue 3 version. A createLatticeGrid component takes the configuration through v-bind, and reactive data flows straight into the grid, so it updates the way the rest of your Vue app does.
The configuration
<link rel="stylesheet" href="https://cdn.latticegrid.dev/lattice-grid@1.107.0/lattice-grid.min.css">
<style>
#grid > div { height: 560px; }
</style>
<div id="grid"></div>
<script type="module">
import * as Vue from 'https://esm.sh/vue@3/dist/vue.esm-browser.prod.js';
import * as lattice from 'https://cdn.latticegrid.dev/lattice-grid@1.107.0/lattice-grid.esm.min.js';
import createLatticeGrid from 'https://cdn.latticegrid.dev/lattice-grid@1.107.0/modules/vue.esm.min.js';
import * as duckdb from 'https://cdn.jsdelivr.net/npm/@duckdb/duckdb-wasm@1.29.0/+esm';
const { createGrid, duckdbAdapter, createPushdownSource } = lattice;
const LatticeGrid = createLatticeGrid({ vue: Vue, createGrid });
// Lattice ships no engine. The page starts DuckDB-Wasm itself and hands the
// adapter a live connection; the grid imports none of it, so the bundle is the
// same size whether this is used or not.
const bundle = await duckdb.selectBundle(duckdb.getJsDelivrBundles());
const worker = await duckdb.createWorker(bundle.mainWorker);
const db = new duckdb.AsyncDuckDB(new duckdb.ConsoleLogger(duckdb.LogLevel.ERROR), worker);
await db.instantiate(bundle.mainModule, bundle.pthreadWorker);
const connection = await db.connect();
// from is any SQL table expression. read_parquet over an HTTP URL streams the
// file; a host that honours range requests lets DuckDB read only the bytes a
// query touches rather than the whole file.
const adapter = duckdbAdapter({
connection,
from: "read_parquet('/demo-data/readings.parquet')",
});
const source = createPushdownSource({
adapter,
compute: lattice, // the grid finishes anything SQL could not express
pageSize: 200,
});
// adapter.sqlFor(query) returns the exact { sql, params } the adapter would run,
// which is how the demo shows the statement without executing it twice.
Vue.createApp({
components: { LatticeGrid },
data() {
return {
config: {
rowKey: 'reading_id',
toolPanel: { side: 'left', panels: ['filters', 'columns'] },
columns: [
{ field: 'reading_id', title: '#', type: 'number' },
{ field: 'plant', title: 'Plant', filter: { type: 'set' } },
{ field: 'line', title: 'Line', filter: { type: 'set' } },
{ field: 'product', title: 'Product' },
{ field: 'bore_mm', title: 'Bore', type: 'millimetres',
spec: { lower: 9.95, upper: 10.05, target: 10 } },
{ field: 'cycle_seconds', title: 'Cycle', type: 'seconds' },
{ field: 'in_spec', title: 'In spec', type: 'boolean' },
],
source, // a hundred thousand rows; DuckDB answers each filter and sort in SQL
},
};
},
template: '<lattice-grid v-bind="config" />',
}).mount('#grid');
</script>