Suche: Stoppwörter für ngram dokumentieren
Neuer Abschnitt „Stoppwörter für ngram (ngram.stopwords)" auf projekt/suche: symmetrische Wirkung auf Index und Anfrage, Presets de/en/fr/es/it, `words` als additive Ergänzung, 0 Treffer bei reinen Stoppwort-Anfragen, Sprach-Hinweis für gemischtsprachige Felder, Re-Index-Richtung (hinzufügen unkritisch, entfernen erst nach Neuaufbau) und Multi-Node-Warnung. Präzisiert nach Second Opinion: - Normalisierung ohne `normalize`-Block ergibt `fuer` (alle Zusatznormalisierer), nur `normalize.use: []` ergibt `fur`. - Setup-Fehler (falscher Modus, Mehr-Wort-Eintrag) landen in der Projekt-Fehlerliste; die Sammlung lädt trotzdem, die Stoppwörter bleiben aus. - `words` ergänzt nur, es gibt keinen Ausnahme-Pfad für Preset-Wörter. - Debug-Liste um `mongo(no-terms)` ergänzt (nur mit vorhandenem Index). Fehlerbilder um drei Fälle erweitert, Stempel aktualisiert (tibi-server 69fc4d8, tibi-types 9e12a8e). reference/schema-properties.md via gen:schemas neu erzeugt, Vollständigkeitstabelle in plans/doku-ausbau.md ergänzt. Build 71 Seiten grün, audit-docs: 0 tote Links/0 kaputte Tabellen.
This commit is contained in:
1 parent
ae15cf398f
commit
5013cceb6f
4 files changed
+51
-7
No files matched your search
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"generatedAt": "2026-10-17T19:58:49.510Z",
|
"generatedAt": "2026-10-19T20:49:08.257Z",
|
||||||
"stats": {
|
"stats": {
|
||||||
"files": 70,
|
"files": 70,
|
||||||
"byDir": {
|
"byDir": {
|
||||||
@@ -13,9 +13,9 @@
|
|||||||
"server": 5
|
"server": 5
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"Aside": 108,
|
"Aside": 109,
|
||||||
"Badge": 30,
|
"Badge": 30,
|
||||||
"Steps": 87,
|
"Steps": 88,
|
||||||
"TabItem": 64,
|
"TabItem": 64,
|
||||||
"Tabs": 28,
|
"Tabs": 28,
|
||||||
"Card": 11,
|
"Card": 11,
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
"src/content/docs/projekt/mcp-nutzen.mdx",
|
"src/content/docs/projekt/mcp-nutzen.mdx",
|
||||||
"src/content/docs/projekt/navigation-i18n.mdx",
|
"src/content/docs/projekt/navigation-i18n.mdx",
|
||||||
"src/content/docs/projekt/ssr-website.mdx",
|
"src/content/docs/projekt/ssr-website.mdx",
|
||||||
|
"src/content/docs/projekt/suche.mdx",
|
||||||
"src/content/docs/reference/schema-properties.md"
|
"src/content/docs/reference/schema-properties.md"
|
||||||
],
|
],
|
||||||
"hollowMarkers": [],
|
"hollowMarkers": [],
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ Jede Fähigkeit von tibi-server / tibi-admin braucht genau eine Dokustelle. Die
|
|||||||
| audit (TTL, Lesen) | projekt/audit-backup | ✅ |
|
| audit (TTL, Lesen) | projekt/audit-backup | ✅ |
|
||||||
| jobs (Cron) + actions | projekt/jobs-actions | ✅ |
|
| jobs (Cron) + actions | projekt/jobs-actions | ✅ |
|
||||||
| snapshots + backup/restore | projekt/audit-backup | ✅ |
|
| snapshots + backup/restore | projekt/audit-backup | ✅ |
|
||||||
| search (Textindex, RRF-Hybrid, Regenerate) | projekt/suche (+ projekt/sammlungen-anlegen für Index-YAML) | ✅ |
|
| search (Textindex, RRF-Hybrid, ngram.stopwords, Regenerate) | projekt/suche (+ projekt/sammlungen-anlegen für Index-YAML) | ✅ |
|
||||||
| embedding + vectorindex (inkl. Failover-Gruppen, Startprüfung/Quarantäne/Rückkehr, `goldenPath`, Status-Endpunkte) | server/konfiguration (Gruppen im Detail), server/betrieb (Status/Störungen), projekt/suche (Kurzüberblick) | ✅ |
|
| embedding + vectorindex (inkl. Failover-Gruppen, Startprüfung/Quarantäne/Rückkehr, `goldenPath`, Status-Endpunkte) | server/konfiguration (Gruppen im Detail), server/betrieb (Status/Störungen), projekt/suche (Kurzüberblick) | ✅ |
|
||||||
| rankfusion (RRF-Formel) | projekt/suche | ✅ |
|
| rankfusion (RRF-Formel) | projekt/suche | ✅ |
|
||||||
| permissions (public/user/token, Orgs/Teams-Matrix) | projekt/rechte-tokens | ✅ |
|
| permissions (public/user/token, Orgs/Teams-Matrix) | projekt/rechte-tokens | ✅ |
|
||||||
|
|||||||
@@ -108,6 +108,46 @@ Alle Modi aus `collection.go:314` — `fields` gilt für `regex` und `ngram`, `v
|
|||||||
Aus Projektsicht musst du nichts einrichten — lass `autoRegenerate: true` in der YAML stehen, dann pflegen sich `fuzzy`- und `semantic`-Indizes selbst. Der Regenerate-Flow im tibi-admin (Test-Plan `41-search-index-status`) nutzt genau den Endpunkt aus Schritt 4.
|
Aus Projektsicht musst du nichts einrichten — lass `autoRegenerate: true` in der YAML stehen, dann pflegen sich `fuzzy`- und `semantic`-Indizes selbst. Der Regenerate-Flow im tibi-admin (Test-Plan `41-search-index-status`) nutzt genau den Endpunkt aus Schritt 4.
|
||||||
</Aside>
|
</Aside>
|
||||||
|
|
||||||
|
## Stoppwörter für `ngram` (`ngram.stopwords`)
|
||||||
|
|
||||||
|
Füllwörter wie „zum", „der" oder „für" treffen in einer n-gram-Suche jeden Text, in dem sie irgendwo vorkommen — auch Beschreibungen, in denen sie nichts aussagen. `ngram.stopwords` entfernt sie aus **beiden** Seiten: aus den gespeicherten N-Grammen und aus der Suchanfrage. Einseitig wäre falsch: stehen gebliebene Stoppwort-N-Gramme blähen die Ähnlichkeitswerte auf und drücken die Unterschiede zwischen relevanten und irrelevanten Treffern zusammen.
|
||||||
|
|
||||||
|
```yaml title="Projekt-YAML — Stoppwörter für fuzzy"
|
||||||
|
search:
|
||||||
|
- name: fuzzy
|
||||||
|
mode: ngram
|
||||||
|
fields: [name, meta.title, meta.description]
|
||||||
|
ngram:
|
||||||
|
sizes: [2, 3]
|
||||||
|
stopwords:
|
||||||
|
presets: [de] # de, en, fr, es, it
|
||||||
|
words: [zum, zur] # optionale Ergänzungen, werden gemerged
|
||||||
|
```
|
||||||
|
|
||||||
|
- Die Presets enthalten reine Funktionswörter: Artikel, Pronomen, Präpositionen, Konjunktionen, Hilfsverben und bedeutungsfreie Adverbien (`internal/utils/ngram_stopwords.go`). Negationswörter wie „nicht" oder „kein" bleiben bewusst draußen — „nicht wasserdicht" würde sonst zur Suche nach „wasserdicht".
|
||||||
|
- Einträge werden mit derselben Normalisiererkette gebildet wie Dokumente und Anfragen. Ohne `normalize`-Block laufen alle Zusatznormalisierer, aus „für" wird `fuer`; nur mit `normalize.use: []` bleibt es beim Standard-Normalisierer und damit bei `fur`. Einträge, die nicht genau ein Wort ergeben, erzeugen einen Projekt-Fehler (`internal/models/collection_setup.go`).
|
||||||
|
- `stopwords` gilt nur für `mode: ngram`. Ein Block mit anderem Modus und gesetzten Stoppwörtern erzeugt einen Projekt-Fehler; das Projekt lädt trotzdem, die Stoppwörter bleiben in diesem Fall aber aus.
|
||||||
|
- Ein Set gilt für den ganzen Block, nicht je Sprache: Es wirkt auf jedes Wort in den konfigurierten Feldern. Bei gemischtsprachigen Inhalten lieber `words` statt Presets nutzen oder einen Block je Sprache anlegen — sonst verschwinden Wörter der falschen Sprache (etwa `car`/`or` aus deutschen Texten, wenn `fr` aktiv ist). `words` ergänzt das Set nur; ein Preset-Wort lässt sich damit nicht wieder freistellen.
|
||||||
|
- Eine Anfrage, die nur aus Stoppwörtern besteht (oder nur aus Begriffen kürzer als jede konfigurierte Größe), liefert **null Treffer** statt der ganzen Sammlung (`internal/utils/ngram.go`).
|
||||||
|
|
||||||
|
### Nach Änderungen neu aufbauen
|
||||||
|
|
||||||
|
`ngram.stopwords` ist Teil des Anreicherungs-Hashs. Hinzufügen ist unkritisch: Die Anfrage verwirft die Wörter, der alte Index enthält nur mehr N-Gramme als nötig. **Entfernen** braucht den Neuaufbau zuerst — sonst liefern diese Wörter null Treffer, bis jedes Dokument neu angereichert ist:
|
||||||
|
|
||||||
|
<Steps>
|
||||||
|
|
||||||
|
1. `stopwords` in der Projekt-YAML ändern und das Projekt neu laden.
|
||||||
|
2. `POST /_/:project/_/admin/regenerate-search` mit `{ collection, modes: ["ngram"] }` aufrufen — oder `autoRegenerate: true` setzen und den Reload abwarten.
|
||||||
|
3. `GET /_/:project/:collection/_queue` beobachten, bis der Zähler 0 ist. Erst danach die alten Wörter aus der Suche nehmen.
|
||||||
|
|
||||||
|
</Steps>
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
Mehrere Server-Instanzen brauchen dieselbe Konfiguration: Ein Knoten ohne (oder mit anderen) Stoppwörtern schreibt einen anderen Config-Hash, markiert die Dokumente der anderen Knoten als veraltet und die `_queue` läuft nie leer.
|
||||||
|
|
||||||
|
Ein Server-Update ohne `stopwords`-Konfiguration ändert nichts: Configs ohne Stoppwörter behalten ihren bisherigen Hash und werden nicht neu aufgebaut. Während ein Neuaufbau läuft, kann ein In-Memory-Index noch N-Gramme nicht regenerierter Dokumente halten; die Treffer nähern sich mit dem Fortschritt an, ein Projekt-Reload baut den Index neu auf.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
## Performance-Optionen (Cache und In-Memory-Index)
|
## Performance-Optionen (Cache und In-Memory-Index)
|
||||||
|
|
||||||
Beide Optionen sind **standardmäßig aus** und ändern ohne Konfiguration nichts.
|
Beide Optionen sind **standardmäßig aus** und ändern ohne Konfiguration nichts.
|
||||||
@@ -159,7 +199,7 @@ search:
|
|||||||
```
|
```
|
||||||
|
|
||||||
- Gebaut wird der Index beim Projekt-(Re-)Load aus den **gespeicherten** `_search`-Ngrammen (nie aus den Quellfeldern), damit er nicht vom MongoDB-Pfad abweichen kann.
|
- Gebaut wird der Index beim Projekt-(Re-)Load aus den **gespeicherten** `_search`-Ngrammen (nie aus den Quellfeldern), damit er nicht vom MongoDB-Pfad abweichen kann.
|
||||||
- Genutzt nur für ngram-Quellen von `combined`-Suchen, und nur wenn er fertig geladen und im Budget ist. Sonst — und immer bei Einzel-ngram-Suchen sowie `_count` — läuft die Suche über MongoDB. Der Debug-Header zeigt `inMemory=ram|mongo(loading)|mongo(budget)|mongo(candidates)`.
|
- Genutzt nur für ngram-Quellen von `combined`-Suchen, und nur wenn er fertig geladen und im Budget ist. Sonst — und immer bei Einzel-ngram-Suchen sowie `_count` — läuft die Suche über MongoDB. Der Debug-Header zeigt `inMemory=ram|mongo(loading)|mongo(budget)|mongo(candidates)|mongo(no-terms)`.
|
||||||
- Rollen-`preFilter`, `?filter=` und Hook-Filter gelten weiter: der Index liefert Kandidaten-IDs, die danach gegen den effektiven Filter geprüft werden.
|
- Rollen-`preFilter`, `?filter=` und Hook-Filter gelten weiter: der Index liefert Kandidaten-IDs, die danach gegen den effektiven Filter geprüft werden.
|
||||||
- Schreibvorgänge (Anlegen/Ändern/Löschen/Bulk/Worker/Regenerate) halten den Index aktuell; **Snapshot- und Backup-Restore bauen alle In-Memory-Zustände neu auf** (Indizes + Cache) — alte Treffer können einen Restore nicht überleben. Während des Neuaufbaus laufen Suchen auf MongoDB.
|
- Schreibvorgänge (Anlegen/Ändern/Löschen/Bulk/Worker/Regenerate) halten den Index aktuell; **Snapshot- und Backup-Restore bauen alle In-Memory-Zustände neu auf** (Indizes + Cache) — alte Treffer können einen Restore nicht überleben. Während des Neuaufbaus laufen Suchen auf MongoDB.
|
||||||
- Budget-Abbruch (zu viele Dokumente, Speicher- oder RSS-Grenze) lässt den Index leer und dauerhaft auf MongoDB; ein Reload startet einen neuen Versuch.
|
- Budget-Abbruch (zu viele Dokumente, Speicher- oder RSS-Grenze) lässt den Index leer und dauerhaft auf MongoDB; ein Reload startet einen neuen Versuch.
|
||||||
@@ -183,10 +223,13 @@ search:
|
|||||||
| Worker-Queue steht | Provider defekt oder überlastet | `search-worker/status` und `embedding/status` lesen, dann Regenerate mit `force: true` |
|
| Worker-Queue steht | Provider defekt oder überlastet | `search-worker/status` und `embedding/status` lesen, dann Regenerate mit `force: true` |
|
||||||
| Suche über `tag`/`navigation` unscharf | `default` ist `regex`, kein Fuzzy | Erwartung anpassen oder `content`-Indexe nutzen |
|
| Suche über `tag`/`navigation` unscharf | `default` ist `regex`, kein Fuzzy | Erwartung anpassen oder `content`-Indexe nutzen |
|
||||||
| `inMemory=ram` erscheint nie im Debug-Header | Globaler Schalter aus, Config ohne `inMemory`, Index noch nicht fertig oder Budget-Abbruch | `search.inMemory.enabled`, `ngram.inMemory.enabled` prüfen, Reload, Budget-Logs lesen |
|
| `inMemory=ram` erscheint nie im Debug-Header | Globaler Schalter aus, Config ohne `inMemory`, Index noch nicht fertig oder Budget-Abbruch | `search.inMemory.enabled`, `ngram.inMemory.enabled` prüfen, Reload, Budget-Logs lesen |
|
||||||
|
| Suche mit einem einzelnen Füllwort liefert nichts | `ngram.stopwords` verwirft das Wort aus der Anfrage | Inhaltliches Wort suchen; soll das Wort suchbar bleiben, das Preset weglassen und das Set nur über `words` bauen |
|
||||||
|
| Ein entferntes Stoppwort liefert weiterhin nichts | Neuaufbau nach dem Entfernen fehlt oder läuft noch | `regenerate-search` anstoßen, `_queue` auf 0 warten |
|
||||||
|
| `mongo(no-terms)` in `X-Search-Sources` | Combined-Quelle ohne verwertbare Terme (nur Stoppwörter oder zu kurze Begriffe) | Kein Fehler — Anfrage präzisieren |
|
||||||
| Nach Restore kurz alte Treffer | Restore erfolgt, Index-Neuaufbau läuft noch | Warten bis `inMemory=ram` wieder erscheint (bis dahin MongoDB-Fallback) |
|
| Nach Restore kurz alte Treffer | Restore erfolgt, Index-Neuaufbau läuft noch | Warten bis `inMemory=ram` wieder erscheint (bis dahin MongoDB-Fallback) |
|
||||||
| Combined-Suche liefert kurz eine ältere Reihenfolge | `combinedCache` aktiv, TTL noch nicht abgelaufen | TTL senken oder Cache für kritische Daten abschalten |
|
| Combined-Suche liefert kurz eine ältere Reihenfolge | `combinedCache` aktiv, TTL noch nicht abgelaufen | TTL senken oder Cache für kritische Daten abschalten |
|
||||||
| `?facet=` an der Suche wirkungslos | Facetten sind eigene Route (`…/_facet`) | [Lesen und suchen](/projekt/abfragen-lesen/) beachten |
|
| `?facet=` an der Suche wirkungslos | Facetten sind eigene Route (`…/_facet`) | [Lesen und suchen](/projekt/abfragen-lesen/) beachten |
|
||||||
|
|
||||||
Weiter: [Lesen und suchen](/projekt/abfragen-lesen/), [Sammlungen anlegen](/projekt/sammlungen-anlegen/), [Felder und Widgets](/projekt/felder-widgets/).
|
Weiter: [Lesen und suchen](/projekt/abfragen-lesen/), [Sammlungen anlegen](/projekt/sammlungen-anlegen/), [Felder und Widgets](/projekt/felder-widgets/).
|
||||||
|
|
||||||
Verifiziert am e3f92eb 2026-10-14 (tibi-svelte-starter), am 68b4278 2026-10-15 (tibi-server, rankfusion), am 2b091d8 2026-10-13 (tibi-admin-nova, Test-Plan 41-search-index-status), am 63a2848c 2026-10-19 (tibi-server: combinedCache, ngram.inMemory, _count-Fast-Path, Restore-Rebuild)
|
Verifiziert am e3f92eb 2026-10-14 (tibi-svelte-starter), am 68b4278 2026-10-15 (tibi-server, rankfusion), am 2b091d8 2026-10-13 (tibi-admin-nova, Test-Plan 41-search-index-status), am 63a2848 2026-10-19 (tibi-server: combinedCache, ngram.inMemory, _count-Fast-Path, Restore-Rebuild), am 69fc4d8 2026-10-19 (tibi-server: ngram.stopwords, Regenerate-Endpunkt, mongo(no-terms)), am 9e12a8e 2026-10-19 (tibi-types: ngram.stopwords/queryFilter/inMemory im Schema)
|
||||||
@@ -400,4 +400,4 @@ Pflicht: `name`.
|
|||||||
| `permissions` | Liste von string | nein | — | Bare permission names for team-based access (Phase 2). Empty = admin-only in Phase 1. |
|
| `permissions` | Liste von string | nein | — | Bare permission names for team-based access (Phase 2). Empty = admin-only in Phase 1. |
|
||||||
| `enabled` | boolean | nein | `false` | Whether this snapshot profile is active. Disabled profiles are skipped by the scheduler but can still be triggered manually. |
|
| `enabled` | boolean | nein | `false` | Whether this snapshot profile is active. Disabled profiles are skipped by the scheduler but can still be triggered manually. |
|
||||||
|
|
||||||
Generiert aus `tibi-types 3bf8055` (Stand 2026-10-17) — Änderungen an den Schemas dort erfordern `npm run gen:schemas`.
|
Generiert aus `tibi-types 9e12a8e` (Stand 2026-10-19) — Änderungen an den Schemas dort erfordern `npm run gen:schemas`.
|
||||||
Reference in new issue
Block a user