11 · Het web als graaf: opslag, analyse en weergave

Onderzoeksagent R11 · 24 september 2026 · regie: agent B · alleen onderzoek, niets in de app gewijzigd

Hoe er gemeten is. Op deze Mac (16 kernen, Node 26.9; de server met Node 24 is niet gemeten). De testgraaf: de 21.476 echte BAG-adressen uit server/data/wijk/ met straat, wijk en bouwdecennium, plus synthetisch 40 knopen en 60 kanten per huis (Sanne heeft er 46 en 60). Samen 0,88 miljoen knopen en 1,33 miljoen kanten. Bundels: esbuild 0.28.2 geminificeerd, daarna gzip -9. De scripts staan in de scratchpad. Wat niet gemeten is, heet schatting.

1 · Samenvatting in tien regels

  1. Blijf bij node:sqlite. Op stadsschaal antwoordt het in 0,1 tot 3 ms op wat een bezoeker vraagt.
  2. De graaf is een afgeleide van relaties, tafel en registers, in twee lagen. De stenen (huis, straat, wijk, bron, jaar, naamgever) mogen vrij geanalyseerd worden; de mensen (jij, zinnen, fans) alleen opgeteld en met k ≥ 5.
  3. LadybugDB, de opvolger van het in oktober 2025 gearchiveerde Kuzu, is jong en zwaarder (740 tegen 130 MB) en heeft geen musl-bouw voor Alpine in de lijst. Dat is iets voor later.
  4. Neo4j en Memgraph geven Cypher en algoritmen, maar ook een tweede plek om persoonsgegevens te wissen. Neo4j's weergave (NVL) mag niet met Community.
  5. RDF (Oxigraph) hoort aan de rand: voor import en voor een latere Linked Data-export. Het gebruikte 1,9 GB voor 1,33 miljoen triples.
  6. Weergave: het huis-web blijft d3-force op eigen canvas, de stad krijgt Sigma.js (37 kB, MIT), later komt @cosmos.gl/graph (MIT). Cosmograph zelf is CC-BY-NC.
  7. Supersexy én begrijpelijk: klein beginnen, plaats die iets betekent, beweging alleen voor wat verandert, en elke lijn leesbaar als zin.
  8. Drie beelden: de stad als sterrenhemel, vier zoomniveaus, en een verhaalpad dat Carmen voorleest.
  9. Elke nuttige analyse lukt in SQL en JavaScript. "Lijkt op" kost 0,7 ms per huis, Louvain op 343 straten 2 ms.
  10. Zaterdag alleen uitbreidingen van het bestaande scherm, de stadsgraaf over twee weken, en een graafdatabase pas bij een meetbare aanleiding.

2 · Opslag en analyse

Optie Kan Gemeten of gedocumenteerd Last, licentie Migratie Zaterdag
(a) node:sqlite + eigen module paden via recursieve CTE of BFS in JS; clusters, centraliteit en gelijkenis in JS (graphology); tijd via sinds/tot laden 3,4 s; 256 MB; ego 1/2/3: 0,1/0,2/2,6 ms; "lijkt op" 0,3 ms; straat × decennium 72 ms; kortste pad 14 ms; 130 MB geheugen geen extra: zelfde bestand en back-up; in Node 24 een release candidate web-graaf.mjs levert al knopen en kanten de hele stad live in milliseconden
(b) LadybugDB (ex-Kuzu) Cypher, kolomopslag, vector- en tekstindex, algoritmen COPY 2,9 s; 112 MB; ego 1/2: 2,4/11 ms; "lijkt op" 217 ms; kortste pad 645 ms; 740 MB geheugen MIT; fork sinds november 2025; binair bestand van 30 MB; geen linux-musl CSV uit SQLite, dan COPY hetzelfde, met Cypher
(c) Neo4j Community Cypher; GDS met alle algoritmen, maar hoogstens 4 threads en 3 modellen niet gemeten; standaard 512 MB heap + 512 MB cache, realistisch 2–4 GB (schatting) GPLv3; tweede container, JVM, synchronisatie neo4j-driver, synchronisatie per nacht Browser achter de schermen; NVL alleen met Aura of commercieel
(d) Memgraph Cypher, 50+ algoritmen (MAGE) volgens hun formule ≈ 0,46 GB zonder eigenschappen (berekend) BSL 1.1 (geen OSI-licentie); alles in geheugen via Bolt Lab achter de schermen
(e) Oxigraph (RDF) SPARQL 1.1, bron per uitspraak, federatie met Wikidata en RCE JS/WASM: laden 3,5 s; ego 1: 12 ms; "lijkt op" 2,5 ms; 1,9 GB geheugen; in JS alleen in geheugen MIT/Apache; de server bewaart wel op schijf alles omzetten naar triples weinig nieuws

Tussen (a) en (b) verschillen de ego-tellingen iets, doordat drukke knopen anders worden overgeslagen; het gaat om de orde van grootte. DuckDB met DuckPGQ is een tussenvorm, maar het is een community-extensie in ontwikkeling en we hebben hem niet nodig.

Advies met fasering

3 · Weergave

Bibliotheek Renderer Soepel tot gzip (gemeten) Licentie Svelte, tokens Toegankelijk, mobiel
d3-force + eigen canvas (nu) Canvas 2D 370 knopen op 60 Hz (gemeten 23-09) 5,7 kB ISC past; leest tokens knoppenlijst, reduced motion, gebaren
Sigma.js 3 + Graphology WebGL ~100k kanten (volgens Linkurious, een concurrent) 37 kB; 45 kB met Louvain en ForceAtlas2 MIT in onMount; tokens via getComputedStyle niets ingebouwd; aanraken werkt
@cosmos.gl/graph WebGL2, lay-out op de GPU "honderdduizenden" 188 kB MIT (Cosmograph: CC-BY-NC-4.0, 578 kB) geen labels, zelf erboven aanraken sinds v3
force-graph / 3d-force-graph Canvas / three.js voorbeeld met ~4k 60 / 375 kB MIT stijl via accessors 3D zwaar op een telefoon; bestaat ook voor VR en AR
AntV G6 5 Canvas, SVG, WebGL, 3D groot (WASM/WebGPU) 430 kB MIT eigen themasysteem niet vastgesteld
Cytoscape.js Canvas; WebGL als preview 1.200 knopen / 16k kanten: 20 → 100+ fps (blog) 139 kB MIT CSS-achtig; algoritmen ingebouwd aanraken werkt
vis-network Canvas enkele duizenden (schatting) 155 kB Apache-2.0/MIT eigen code gedateerd
deck.gl + graph-layers WebGL2/WebGPU experimenteel 530 kB MIT sterk op een kaart experimenteel
Gephi Lite app op Sigma — — GPL-3 niet inbouwen; wel als teamgereedschap —

Om hun licentie vallen ook af: Neo4j NVL (volgens LICENSE.txt in het npm-pakket alleen voor Aura of commercieel Neo4j) en deepscatter, de motor van Nomic Atlas (CC BY-NC-SA).

Advies

4 · Drie beeldideeën

Wat werkt: klein beginnen en uitvouwen (Kumu: de hele kaart in één keer overweldigt), dimmen in plaats van verbergen (showcase), een tijdschuif als verhaalstap (Flourish) en één boodschap per beeld (The Pudding). Daarbij onze eigen regels: goud alleen als haarlijn voor een band met jou (MASTER §10), papier voor wat je leest (§9), nachtblauw voor de kamer (§11).

A · De stad als sterrenhemel

B · Vier zoomniveaus

C · Verhaalpad

5 · Analyses die iets opleveren

Analyse Voor wie Hoe (gemeten waar het kon) Graafdatabase? Grens
Lijkt op jouw huis bezoeker: "Acht van ons…" vector (bouwjaar, oppervlak, water, park, bomen, rust, ochtendzon) plus gedeelde buren; top-10 in 0,7 ms, alle huizen in 3,5 s nee een ander huis heet alleen naar zijn straat
Straten die rijmen Carmen: "Ik heb drie straten" k-NN (k=5) en dan Louvain: 343 straten, 13 groepen, 2 ms nee vast zaadje; een mens geeft de namen
Dromen per thema per straat of wijk eigenaar, wijk kanten van thema naar straat, HAVING count(DISTINCT persoon) >= 5 nee k ≥ 5, nooit een lijst
Ontbrekende kennis wij (oogst) anti-join: straat zonder naamverklaring, feit zonder bron nee —
Kern van een web redactie de drie tellingen uit v3 §7 nee wordt nooit benoemd
Centraliteit van bronnen wij graphology-metrics nee huizen nooit rangschikken (D6)
Wat mensen leuk vinden wij per soort relatie en verhaalpad tellen hoe vaak "klopt", ♥ of bewaard volgt nee opgeteld, k ≥ 5, geen persoons-id
Web door de tijd zaal sinds/tot nee niet faken (D51)

Aanbod en vraag. Aan de aanbodkant is genoeg: van de 343 straten hebben er 133 ochtendzon, 245 water binnen 100 m, 147 zijn rustig en 146 hebben een park binnen 150 m. De vraagkant is in de demo te dun voor k ≥ 5, dus we beginnen per wijk (v3 §13). Een graafdatabase helpt pas bij patronen van wisselende lengte, embeddings op structuur, of data groter dan het geheugen.

6 · Podium

Hoe je een hairball voorkomt (zie Grooming the hairball):

  1. Teken opgetelde kanten, per knoop hoogstens de 5 sterkste.
  2. Maak een drukke knoop een plek in de kantlijn in plaats van een knoop.
  3. Geef vaste posities of een vooraf berekende lay-out.
  4. Gebruik semantische zoom.
  5. Dim wat buiten de keuze valt in plaats van het te verbergen.
  6. Toon hoogstens ~150 knopen per beeld (vuistregel).

7 · Plan op agent-niveau

Prijzen per miljoen tokens (Anthropic, juni 2026): Opus 5 $5 in / $25 uit (Opus 5.5 $4/$20), Sonnet 5 $2/$10, Haiku 4.5 $1/$5; cache lezen ≈ een tiende daarvan. Met een aangenomen koers van $1 ≈ €0,90 kost een agentuur naar schatting €8–15 met Opus, €3–6 met Sonnet en €1–3 met Haiku.

# Stap Wanneer Model Uren € (schatting) Risico
1 Afspeelknop en verhaalpad in Web.svelte, achter een parameter 24–25 sep Opus 2–3 20–45 regressie vóór de oefening
2 GET /api/stad/web (alleen lezen, zonder personen) plus een eenvoudige sterrenhemel alleen als stap 1 donderdag af is Opus 3–4 30–60 tijd
3 QA en lekcontrole na 1 en 2 agent B 1 — —
4 0003-web.sql, projectie, "wis alles" en reset, lektests week 40 Opus 6–8 50–120 tweede kopie van persoonsdata
5 lib/graaf en een nachtjob met graphology week 40 Sonnet 4–6 15–35 goed af te bakenen na stap 4
6 Stadsweergave met Sigma: zoomniveaus, tokens, toegankelijkheid, telefoon week 40–41 Opus 8–10 70–150 labels, prestaties op de telefoon
7 Rijmgroepen een naam geven, straatnamen aanvullen met bron week 41 Haiku, Opus keurt 2–4 5–20 verzinsels; alleen met een bron-url die 200 gaf
8 Drie verhaalpaden en een reservevideo week 41 Sonnet 2 8–12 —
9 Sterrenhemel op cosmos.gl later Opus 12–16 120–240 WebGL op de zaalapparatuur
10 Proef met LadybugDB als zijspoor alleen met een aanleiding Opus 4 35–60 jonge fork

Opgeteld: nu €50–105, over twee weken €150–340, later €155–300. E wil sinds 24 september doe-werk door Opus; voor stap 5, 7 en 8 is dat ongeveer 2,5 keer zo duur.

8 · Wat we niet moeten doen

Bronnen. Kuzu naar Ladybug · Neo4j GDS, grenzen · Neo4j in Docker · NVL · Memgraph, geheugen · Memgraph, licentie · Oxigraph JS · node:sqlite · cosmos.gl v3 · Sigma · G6 · 3d-force-graph · deck.gl-community · Gephi Lite · deepscatter