Facetten zur Suche dokumentieren (tibi-server #38)
- abfragen-lesen: Abschnitt "Suchbewusste Facetten" (q/qName/qLimit, search-Block, Default-Fenster rrf.topK, 20000er-Deckel) - suche: topK-Default 500, q gilt auch für _count/_facet, zwei Fehlerbild-Zeilen - mcp-nutzen: documents_facet mit q/qName/qLimit - doku-ausbau: Vollständigkeitszeile ergänzt - Stempel auf tibi-server d0d699d
This commit is contained in:
1 parent
818fb76d61
commit
5d9abe4dc9
5 files changed
+37
-7
No files matched your search
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"generatedAt": "2026-10-20T00:51:22.849Z",
|
"generatedAt": "2026-10-20T01:44:24.935Z",
|
||||||
"stats": {
|
"stats": {
|
||||||
"files": 70,
|
"files": 70,
|
||||||
"byDir": {
|
"byDir": {
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ Jede Fähigkeit von tibi-server / tibi-admin braucht genau eine Dokustelle. Die
|
|||||||
| search (Textindex, RRF-Hybrid, ngram.stopwords, 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 | ✅ |
|
||||||
|
| suchbewusste Facetten (`_facet` mit `q`/`qName`/`qLimit`, `search`-Block, `rrf.topK`-Default 500) | projekt/abfragen-lesen (+ projekt/suche) | ✅ |
|
||||||
| permissions (public/user/token, Orgs/Teams-Matrix) | projekt/rechte-tokens | ✅ |
|
| permissions (public/user/token, Orgs/Teams-Matrix) | projekt/rechte-tokens | ✅ |
|
||||||
| filecleanup (automatisch, keine Config-Fläche) | kein eigener Artikel — Einzeiler in server/betrieb prüfen (T-FINISH) | ⏳ |
|
| filecleanup (automatisch, keine Config-Fläche) | kein eigener Artikel — Einzeiler in server/betrieb prüfen (T-FINISH) | ⏳ |
|
||||||
| cache (Hook-lokal) | projekt/hooks-schreiben (Kontext-Tabelle) | ✅ |
|
| cache (Hook-lokal) | projekt/hooks-schreiben (Kontext-Tabelle) | ✅ |
|
||||||
|
|||||||
@@ -104,9 +104,33 @@ Ein `lookup` löst nur auf, wenn der Zieldatensatz für dich lesbar ist — dazu
|
|||||||
| `GET …/<collection>/_facet?facet=<feld>` | Werte zählen je Feld | `GET …/comment/_facet?facet=contentId` |
|
| `GET …/<collection>/_facet?facet=<feld>` | Werte zählen je Feld | `GET …/comment/_facet?facet=contentId` |
|
||||||
| `…/_facet?facet=<feld>&limit=10` | Nur Top N | `GET …/comment/_facet?facet=contentId&limit=10` |
|
| `…/_facet?facet=<feld>&limit=10` | Nur Top N | `GET …/comment/_facet?facet=contentId&limit=10` |
|
||||||
| `…/_facet?facet=<feld>&includeEmpty=1` | Leere Werte mitzählen | `GET …/comment/_facet?facet=tags&includeEmpty=1` |
|
| `…/_facet?facet=<feld>&includeEmpty=1` | Leere Werte mitzählen | `GET …/comment/_facet?facet=tags&includeEmpty=1` |
|
||||||
|
| `…/_facet?facet=<feld>&q=<text>&qName=<block>` | Werte **der Treffer** zählen | `GET …/productVariant/_facet?facet=brand&q=warme jacke&qName=combined` |
|
||||||
|
|
||||||
Die Kommentar-Anzahl je Seite (`commentCount`) kommt aus so einer Abfrage über `contentId`.
|
Die Kommentar-Anzahl je Seite (`commentCount`) kommt aus so einer Abfrage über `contentId`.
|
||||||
|
|
||||||
|
### Suchbewusste Facetten
|
||||||
|
|
||||||
|
`q` und `qName` gelten auch für `_facet`: Die Zählung bezieht sich dann auf die Trefferliste, nicht auf die ganze Sammlung.
|
||||||
|
Damit passt sich eine Filterseitenleiste der Suche an.
|
||||||
|
|
||||||
|
| Parameter | Bedeutung |
|
||||||
|
|---|---|
|
||||||
|
| `q`, `qName` | Suchtext und Suchblock; gezählt werden nur noch die Treffer |
|
||||||
|
| `qLimit` | Zahl, `0` oder `all`: wie viele Treffer die Zählung abdeckt |
|
||||||
|
|
||||||
|
```text title="Facetten zur Suche"
|
||||||
|
GET …/productVariant/_facet?facet=catalogProjection.brand&q=warme jacke&qName=combined
|
||||||
|
GET …/productVariant/_facet?facet=catalogProjection.brand&q=warme jacke&qName=combined&qLimit=all
|
||||||
|
```
|
||||||
|
|
||||||
|
- Ohne `qLimit` ist das Fenster so groß wie `rrf.topK` des Suchblocks (ohne Angabe 500, siehe [Suche](/projekt/suche/)) — also genau die Menge, die die Liste zeigt.
|
||||||
|
- `qLimit=all` (oder `qLimit=0`) zählt alle Treffer; der Server deckelt bei 20 000 IDs. `qLimit=<zahl>` setzt das Fenster selbst.
|
||||||
|
- Ein größeres Fenster als `rrf.topK` liefert bewusst mehr Treffer als die Liste zeigt: die Summe der Facettenwerte ist dann größer als die Trefferzahl der Liste.
|
||||||
|
- Bei den filterbasierten Modi (`text`, `regex`, `ngram`, `eval`, `filter`) wird `qLimit` ignoriert — dort zählt der Filter ohnehin exakt.
|
||||||
|
- Nur bei den Modi `vector` und `combined` ergänzt die Antwort einen Block `search`, z. B. `{"mode":"combined","resolved":500,"limit":500,"truncated":true}`. `truncated: true` heißt: Fenster voll, weitere Treffer sind möglich — auch wenn es exakt aufgeht, denn der Server holt kein Extra-Dokument.
|
||||||
|
- Die Modi `text`, `regex`, `ngram`, `eval` und `filter` setzen `q` als MongoDB-Filter um. Dort ist die Zählung exakt und es gibt keinen `search`-Block.
|
||||||
|
- Ohne Treffer kommt eine leere Facetten-Antwort ohne Datenbankzugriff.
|
||||||
|
|
||||||
## Aggregate: Rückwärts zählen und rechnen (Listen-Route!)
|
## Aggregate: Rückwärts zählen und rechnen (Listen-Route!)
|
||||||
|
|
||||||
`aggregate` hängt an der normalen `GET`-Liste — **kein** eigener Endpunkt wie `_count`/`_facet`.
|
`aggregate` hängt an der normalen `GET`-Liste — **kein** eigener Endpunkt wie `_count`/`_facet`.
|
||||||
@@ -162,4 +186,4 @@ GET …/tag?q=hero
|
|||||||
| Leere Liste trotz Daten | `filter_public`-Hook filtert `active:true` + Zeitraum ([Rechte und Tokens](/projekt/rechte-tokens/)) | `active:true` setzen, `publication`-Fenster prüfen |
|
| Leere Liste trotz Daten | `filter_public`-Hook filtert `active:true` + Zeitraum ([Rechte und Tokens](/projekt/rechte-tokens/)) | `active:true` setzen, `publication`-Fenster prüfen |
|
||||||
| `_lookup` leer | Zieldatensatz nicht lesbar (meist `active:true` fehlt, siehe [Rechte und Tokens](/projekt/rechte-tokens/)) | Zieldatensatz prüfen, nicht die Abfrage |
|
| `_lookup` leer | Zieldatensatz nicht lesbar (meist `active:true` fehlt, siehe [Rechte und Tokens](/projekt/rechte-tokens/)) | Zieldatensatz prüfen, nicht die Abfrage |
|
||||||
|
|
||||||
Verifiziert am e3f92eb 2026-10-17 (tibi-svelte-starter), am 68b4278 2026-10-17 (tibi-server, collection_get/select/sort/facet/count/lookup), am 68b4278 2026-10-17 (tibi-server, aggregate: dbapi/aggregate.go, controller/collection_aggregate.go)
|
Verifiziert am e3f92eb 2026-10-17 (tibi-svelte-starter), am 68b4278 2026-10-17 (tibi-server, collection_get/select/sort/facet/count/lookup), am 68b4278 2026-10-17 (tibi-server, aggregate: dbapi/aggregate.go, controller/collection_aggregate.go), am d0d699d 2026-10-20 (tibi-server: collection_facet.go, collection_facet_search.go, rrf.topK-Default)
|
||||||
@@ -137,9 +137,11 @@ Fehler: ohne Leserecht am Ziel → 403 (`permission denied` bzw. Scope-Fehler).
|
|||||||
|
|
||||||
### documents_facet — Werte je Feld zählen
|
### documents_facet — Werte je Feld zählen
|
||||||
|
|
||||||
Signatur: `namespace*`, `collection*`, `fields*`, optional `filter`, `extra`. Scope: `namespace.<ns>.<col>.read`. Methode: `GET`.
|
Signatur: `namespace*`, `collection*`, `fields*`, optional `filter`, `q`, `qName`, `qLimit`, `extra`. Scope: `namespace.<ns>.<col>.read`. Methode: `GET`.
|
||||||
|
|
||||||
`tools/call`: `{"name":"documents_facet","arguments":{"namespace": "<ns>", "collection": "content", "fields": "status"}}`
|
`tools/call`: `{"name":"documents_facet","arguments":{"namespace": "<ns>", "collection": "content", "fields": "status", "q": "kontakt", "qName": "combined"}}`
|
||||||
|
|
||||||
|
Mit `q`/`qName` zählen die Werte nur über den Treffern der Suche; `qLimit` (Zahl oder `all`) weitet das Fenster über `rrf.topK` hinaus ([Lesen und suchen](/projekt/abfragen-lesen/)).
|
||||||
|
|
||||||
Fehler: ohne `fields` → 400 (`missing required parameter: facet` auf Controller-Ebene).
|
Fehler: ohne `fields` → 400 (`missing required parameter: facet` auf Controller-Ebene).
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ GET …/content?q=kontakt&qName=combined&qExplain=1
|
|||||||
```
|
```
|
||||||
|
|
||||||
- `q` ist der Suchtext, `qName` wählt den Block (ohne `qName` greift der Standard).
|
- `q` ist der Suchtext, `qName` wählt den Block (ohne `qName` greift der Standard).
|
||||||
|
- `q` und `qName` gelten auch für `_count` und `_facet` — Facetten zählen dann nur die Treffer ([Lesen und suchen](/projekt/abfragen-lesen/)).
|
||||||
- `qExplain=1` zeigt die Gewichtung — nützlich beim Debuggen.
|
- `qExplain=1` zeigt die Gewichtung — nützlich beim Debuggen.
|
||||||
- Suche mit und ohne `lookup` testen: `?q=…&qName=combined&lookup=blocks.heroImage.image:medialib,blocks.image:medialib` löst Treffer-Bilder gleich auf.
|
- Suche mit und ohne `lookup` testen: `?q=…&qName=combined&lookup=blocks.heroImage.image:medialib,blocks.image:medialib` löst Treffer-Bilder gleich auf.
|
||||||
|
|
||||||
@@ -70,7 +71,8 @@ GET …/content?q=kontakt&qName=combined&qExplain=1
|
|||||||
score(doc) += weight / (k + rank) # k = 60, weights: semantic 1.5, fuzzy 1.0
|
score(doc) += weight / (k + rank) # k = 60, weights: semantic 1.5, fuzzy 1.0
|
||||||
```
|
```
|
||||||
|
|
||||||
- `topK: 100` begrenzt die Kandidaten je Quelle **und** kappt das Fusionsergebnis (`MergeRRF`).
|
- `topK: 100` begrenzt die Kandidaten je Quelle **und** kappt das Fusionsergebnis (`MergeRRF`). Ohne Angabe im `rrf`-Block gilt `topK: 500`.
|
||||||
|
- Das gekappte Fusionsergebnis ist die Treffermenge der Liste **und** das Standardfenster der Facetten (`_facet?q=…`).
|
||||||
- Weitere Strategien (`score_rrf`, `score_sum`, `rank_score`, `hybrid`), Normierung (`minmax`, `zscore`), Gewichte (`scoreWeight`) und Quellen-Config (`sourceConfig`) existieren im Code **und** sind als `rrf`-Block in der Projekt-YAML einstellbar — aus Projektsicht reicht `combined` mit den Starter-Gewichten.
|
- Weitere Strategien (`score_rrf`, `score_sum`, `rank_score`, `hybrid`), Normierung (`minmax`, `zscore`), Gewichte (`scoreWeight`) und Quellen-Config (`sourceConfig`) existieren im Code **und** sind als `rrf`-Block in der Projekt-YAML einstellbar — aus Projektsicht reicht `combined` mit den Starter-Gewichten.
|
||||||
- Alte Score-Beispiele aus Erzähl-Docs nicht übernehmen — nur diese Formel gilt.
|
- Alte Score-Beispiele aus Erzähl-Docs nicht übernehmen — nur diese Formel gilt.
|
||||||
|
|
||||||
@@ -240,8 +242,9 @@ Zwei Dense-Speicherformen sind im Umlauf: BSON-Binary (aktuell) und ein Legacy-B
|
|||||||
| `X-Search-Memory: mongo(lookup)` / `mongo(aggregate)` / `mongo(hook-pipeline)` / `mongo(hook-filter)` | Anfrage nutzt Schritte oder einen Hook-Filter, die in der MongoDB-Pipeline laufen | Erwartetes Verhalten; ohne diese Parameter messen |
|
| `X-Search-Memory: mongo(lookup)` / `mongo(aggregate)` / `mongo(hook-pipeline)` / `mongo(hook-filter)` | Anfrage nutzt Schritte oder einen Hook-Filter, die in der MongoDB-Pipeline laufen | Erwartetes Verhalten; ohne diese Parameter messen |
|
||||||
| 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 Liste wirkungslos | Facetten sind eine eigene Route (`…/_facet`) | `q`/`filter` dort mitgeben — [Lesen und suchen](/projekt/abfragen-lesen/) |
|
||||||
|
| Facettenzahlen kleiner als erwartet | Fenster ist `rrf.topK` (Default 500), nicht die ganze Sammlung | `?qLimit=all` an `_facet` setzen oder `topK` im `rrf`-Block erhöhen |
|
||||||
|
|
||||||
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 63a2848 2026-10-19 (tibi-server: combinedCache, ngram.inMemory, _count-Fast-Path, Restore-Rebuild), am 76f1336 2026-10-19 (tibi-server: ngram.stopwords, Regenerate-Endpunkt, mongo(no-terms)); am 92c3ad74 2026-10-20 (tibi-server: kompakter ngramindex, collection_ngram_search.go, Hook-Pipeline-Klassifikation, X-Search-Memory), am 654b568 2026-10-19 (tibi-server: kompakter Sparse-Vektorindex, Legacy-Dense-Format, MemoryEstimate, vectormigrate, paralleler Range-Loader inkl. Retry/Semaphore), am 9e12a8e 2026-10-19 (tibi-types: ngram.stopwords/queryFilter/inMemory im Schema), am 21472bd 2026-10-19 (tibi-types: ngram.sizes 2–10, combinedCache im Schema), am cf44cd7 2026-10-19 (tibi-svelte-starter: tibi-types-Submodul auf 21472bd)
|
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 76f1336 2026-10-19 (tibi-server: ngram.stopwords, Regenerate-Endpunkt, mongo(no-terms)); am 92c3ad74 2026-10-20 (tibi-server: kompakter ngramindex, collection_ngram_search.go, Hook-Pipeline-Klassifikation, X-Search-Memory), am 654b568 2026-10-19 (tibi-server: kompakter Sparse-Vektorindex, Legacy-Dense-Format, MemoryEstimate, vectormigrate, paralleler Range-Loader inkl. Retry/Semaphore), am 9e12a8e 2026-10-19 (tibi-types: ngram.stopwords/queryFilter/inMemory im Schema), am 21472bd 2026-10-19 (tibi-types: ngram.sizes 2–10, combinedCache im Schema), am cf44cd7 2026-10-19 (tibi-svelte-starter: tibi-types-Submodul auf 21472bd), am d0d699d 2026-10-20 (tibi-server: collection_facet_search.go, rrf.topK-Default 500, qLimit)
|
||||||
Reference in new issue
Block a user