From 7886947a65bdae7fb64dab0a835253b2a96e9e0e Mon Sep 17 00:00:00 2001 From: beo3000 Date: Sun, 22 Feb 2026 22:05:07 +0100 Subject: [PATCH] link fix --- ka-note/VERSION | 2 +- .../lib/components/CompanyPersonsView.svelte | 19 +++++++++++------ roadmap.md | 21 +++++++++++++++++++ 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/ka-note/VERSION b/ka-note/VERSION index db06d56..91a821f 100644 --- a/ka-note/VERSION +++ b/ka-note/VERSION @@ -1 +1 @@ -1.1.5 \ No newline at end of file +1.1.7 \ No newline at end of file diff --git a/ka-note/client/src/lib/components/CompanyPersonsView.svelte b/ka-note/client/src/lib/components/CompanyPersonsView.svelte index 72e8d32..9af8fc5 100644 --- a/ka-note/client/src/lib/components/CompanyPersonsView.svelte +++ b/ka-note/client/src/lib/components/CompanyPersonsView.svelte @@ -14,21 +14,28 @@ const linkedPersons = liveQuery(async () => { const allHistory = await db.historyEntries.filter(h => !h.deletedAt).toArray(); + const allTopics = await db.topics.filter(t => !t.deletedAt).toArray(); const personContexts = await db.contexts.filter(c => !c.deletedAt && c.type === 'person').toArray(); + // Persons referenced in history entries that mention this company const matchingPersonNames = new Set(); for (const h of allHistory) { if (extractCompanies(h.text).includes(entityName)) { - for (const m of extractMentions(h.text)) { - matchingPersonNames.add(m); - } - for (const a of extractAssignments(h.text)) { - matchingPersonNames.add(a); - } + for (const m of extractMentions(h.text)) matchingPersonNames.add(m); + for (const a of extractAssignments(h.text)) matchingPersonNames.add(a); + } + } + + // Person contexts whose topics mention this company directly + const personContextIdsWithCompanyInTopics = new Set(); + for (const t of allTopics) { + if (extractCompanies(t.body ?? '').includes(entityName)) { + personContextIdsWithCompanyInTopics.add(t.contextId); } } return personContexts.filter(p => { + if (personContextIdsWithCompanyInTopics.has(p.id)) return true; const pName = p.name.replace(/^Person\s+/, ''); return matchingPersonNames.has(pName); }); diff --git a/roadmap.md b/roadmap.md index fc8823e..7210ec6 100644 --- a/roadmap.md +++ b/roadmap.md @@ -25,3 +25,24 @@ Szenario: Gerät A löscht Item (version N+1), hat aber noch nie gepusht. Gerät **Empfehlung** Option 2 (Tombstones) für korrekte Multi-Gerät-Unterstützung. Option 3 als pragmatischer Zwischenschritt wenn Full-Sync (since=null) garantiert ist. + +--- + +## [LOW] Verlinkung: Index für @F:/@P:/@NAME-Tags + +**Aktueller Stand** +`CompanyPersonsView` und ähnliche Views scannen beim Öffnen alle Topics + History-Einträge per Regex (O(n) über gesamten Content, in-memory via Dexie). + +**Skalierbarkeit** +Für den typischen PKM-Anwendungsfall (< 10.000 Einträge, ein User, lokal) kein Problem. Ab ~5.000 Einträgen potenziell spürbar (> 200ms). + +**Lösungsoptionen** + +1. **Berechnetes Feld beim Schreiben** (pragmatisch) + Beim Speichern eines Topics/History-Eintrags die Tags extrahieren und als Array in einer eigenen Spalte speichern (`companyRefs: string[]`, `personRefs: string[]`). Dexie kann darauf einen echten `MultiEntry`-Index anlegen → O(1) Lookup statt O(n) Scan. Kein Background-Worker nötig. + +2. **SQLite FTS5 (serverseitig)** + Volltext-Index auf dem Server, Lookup per API. Höherer Aufwand, sinnvoll erst bei Multi-User-Szenarien. + +**Empfehlung** +Nichts ändern bis die Query spürbar langsam wird. Dann Option 1 (berechnetes Feld + Dexie MultiEntry-Index) als einfachster Mittelweg.