OG
JS
Docs
Demos
Examples
Filter workbench
Compose predicates over a large graph, then inspect visible topology and local elapsed time.
Minimum score
0
50
70
90
Region
All
North
South
Apply filters
Clear filters
building workload…
—
// The URL controls workload size while node data supplies filterable region and risk fields. // OGJS composes filters over retained topology and exposes detached visible-node and // visible-edge snapshots, so reporting never reads internal typed-array flags. import { Ogjs } from '../../src/index'; import { BenchmarkRunner } from '../../src/benchmark/index'; const params = new URLSearchParams(location.search); const requested = params.has('nodes') ? Number(params.get('nodes')) : Number.NaN; const nodeCount = Number.isInteger(requested) ? Math.max(100, Math.min(100000, requested)) : 20000; const edgeCount = nodeCount * 2; const regions = ['north', 'east', 'south', 'west']; const nodes = Array.from({ length: nodeCount }, (_, index) => ({ id: index, size: 2.5, color: ['#2563eb', '#0891b2', '#059669', '#9333ea'][index % 4], data: { score: index % 100, region: regions[Math.floor(index / 100) % 4] }, })); const edges = Array.from({ length: edgeCount }, (_, index) => { const source = index % nodeCount; const blockStart = Math.floor(source / 100) * 100; const blockSize = Math.min(100, nodeCount - blockStart); const offset = index < nodeCount ? 1 : 2; const target = blockStart + (source - blockStart + offset) % blockSize; return { source, target }; }); const og = new Ogjs({ container: '#viz', theme: 'light', accessibility: false, labels: { minZoom: 99 } }); const runner = new BenchmarkRunner(og); og.setGraph({ nodes, edges }); // A grid is presentation intent, not workload data. OGJS derives its row and column count // from the requested graph size and keeps the fixture free of canvas geometry. og.layouts.grid(8); og.camera.fit(); const score = document.querySelector('#score'); const region = document.querySelector('#region'); const status = document.querySelector('#status'); const metrics = document.querySelector('#metrics'); function report(operation, count) { const graph = og.stats(); // Public visibility snapshots return stable ids and relationships. Reporting therefore does // not depend on private flag arrays and remains valid if renderer storage changes. const visibleIds = new Set(og.getVisible()); const visibleNodes = visibleIds.size; const visibleEdges = og.getVisibleEdges() .filter(({ source, target }) => visibleIds.has(source) && visibleIds.has(target)) .length; const filterReport = { schema: 'ogjs-filter-run/v1', workload: { nodes: graph.nodes, edges: graph.edges }, predicates: { minimumScore: Number(score.value), region: region.value, count }, timing: { elapsedMs: operation.elapsedMs }, result: { visibleNodes, hiddenNodes: graph.nodes - visibleNodes, visibleEdges, hiddenEdges: graph.edges - visibleEdges, }, }; status.textContent = `${visibleNodes.toLocaleString()} visible · ${graph.nodes - visibleNodes} hidden`; metrics.textContent = `${visibleEdges.toLocaleString()} visible links · ${filterReport.timing.elapsedMs.toFixed(2)} ms`; } document.querySelector('#apply').addEventListener('click', () => { // Recreate the composed query from current controls. Hidden records stay in the graph, so // Clear restores the original view without reloading or rerunning the layout. const minimum = Number(score.value); const selected = region.value; const count = selected === 'all' ? 1 : 2; const operation = runner.measureFilter(({ data }) => ( data.score >= minimum && (selected === 'all' || data.region === selected) )); report(operation, count); }); document.querySelector('#clear').addEventListener('click', () => { report(runner.measureFilter(), 0); }); status.textContent = `ready · ${nodeCount.toLocaleString()} nodes`;