Suche: Hook-Filter und lookup/aggregate präzisieren
Deploy tibi-docs / build-and-deploy (push) Failing after 32s

`?lookup=`/`?aggregate=` erzwingen MongoDB (Projektionen wirken weiter), und
ein Hook-Filter fällt als mongo(hook-filter) zurück. Fehlerbilder ergänzt.
This commit is contained in:
apairon committed 2026-10-20 00:35:24 +00:00
1 parent 8d296833ad
commit d9b3df10c3
2 files changed
+4 -4

No files matched your search

+1 -1
View File
@@ -1,5 +1,5 @@
{ {
"generatedAt": "2026-10-20T00:27:05.884Z", "generatedAt": "2026-10-20T00:33:33.673Z",
"stats": { "stats": {
"files": 70, "files": 70,
"byDir": { "byDir": {
+3 -3
View File
@@ -199,8 +199,8 @@ 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 wird er für ngram-Quellen von `combined`-Suchen **und für Einzel-ngram-Suchen** — dort ersetzt er nur das Ranking, die Seitendokumente werden anschließend per `_id` geladen (Projektion, `lookup` und Aggregation bleiben also nutzbar). Bei `combined` zeigt der Debug-Header `inMemory=ram|mongo(loading)|mongo(budget)|mongo(candidates)|mongo(no-terms)`; `mongo(no-terms)` erscheint nur, wenn für die Quelle überhaupt ein In-Memory-Index existiert. - Genutzt wird er für ngram-Quellen von `combined`-Suchen **und für Einzel-ngram-Suchen** — dort ersetzt er nur das Ranking, die Seitendokumente werden anschließend per `_id` geladen (Projektionen/`?select` wirken weiter; `?lookup=` und `?aggregate=` erzwingen dagegen MongoDB). Bei `combined` zeigt der Debug-Header `inMemory=ram|mongo(loading)|mongo(budget)|mongo(candidates)|mongo(no-terms)`; `mongo(no-terms)` erscheint nur, wenn für die Quelle überhaupt ein In-Memory-Index existiert.
- Einzel-ngram-Suchen fallen mit `X-Search-Debug: true` im Kopf `X-Search-Memory` sichtbar auf MongoDB zurück, wenn der Index nicht bereit ist oder die Anfrage etwas braucht, das der Index nicht garantieren kann: `mongo(disabled)`, `mongo(loading)`, `mongo(budget)`, `mongo(count)` (bei `?count=1`), `mongo(sort)` (bei eigenem `?sort=`), `mongo(no-terms)` — sowie `mongo(lookup)`, `mongo(aggregate)` und `mongo(hook-pipeline)`, wenn die Anfrage Schritte braucht, die in der MongoDB-Pipeline laufen. Ein `pipelineMod` aus einem Read-Hook stört den RAM-Pfad nur, wenn er die Ergebnismenge ändern kann (`$match`, `$sort`, `$group`, `$project`, …), Stufen vor die bestehende Pipeline setzt oder `_id`/`_search` schreibt bzw. `$_search` liest. Reine angehängte Feld-Transformationen (`$addFields`, `$set`, `$unset`) laufen auf der geladenen Seite nach der Projektion und bleiben im RAM. - Einzel-ngram-Suchen fallen mit `X-Search-Debug: true` im Kopf `X-Search-Memory` sichtbar auf MongoDB zurück, wenn der Index nicht bereit ist oder die Anfrage etwas braucht, das der Index nicht garantieren kann: `mongo(disabled)`, `mongo(loading)`, `mongo(budget)`, `mongo(count)` (bei `?count=1`), `mongo(sort)` (bei eigenem `?sort=`), `mongo(no-terms)` — sowie `mongo(lookup)`, `mongo(aggregate)`, `mongo(hook-pipeline)` und `mongo(hook-filter)`, wenn die Anfrage Schritte braucht, die in der MongoDB-Pipeline laufen. Ein `pipelineMod` aus einem Read-Hook stört den RAM-Pfad nur, wenn er die Ergebnismenge ändern kann (`$match`, `$sort`, `$group`, `$project`, …), Stufen vor die bestehende Pipeline setzt oder `_id`/`_search` schreibt bzw. `$_search` liest. Reine angehängte Feld-Transformationen (`$addFields`, `$set`, `$unset`) laufen auf der geladenen Seite nach der Projektion und bleiben im RAM.
- 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.
@@ -237,7 +237,7 @@ Zwei Dense-Speicherformen sind im Umlauf: BSON-Binary (aktuell) und ein Legacy-B
| `X-Search-Memory: mongo(disabled)` bei jeder Suche | In-Memory-Index nicht aktiviert oder nicht geladen | `search.inMemory.enabled` und `ngram.inMemory.enabled` prüfen, Projekt neu laden | | `X-Search-Memory: mongo(disabled)` bei jeder Suche | In-Memory-Index nicht aktiviert oder nicht geladen | `search.inMemory.enabled` und `ngram.inMemory.enabled` prüfen, Projekt neu laden |
| `X-Search-Memory: mongo(budget)` | Index-Load über dem Budget abgebrochen (Doc-Anzahl, Speicher oder RSS) | Budget erhöhen oder Collection kleiner halten; Loader-Log lesen | | `X-Search-Memory: mongo(budget)` | Index-Load über dem Budget abgebrochen (Doc-Anzahl, Speicher oder RSS) | Budget erhöhen oder Collection kleiner halten; Loader-Log lesen |
| `X-Search-Memory: mongo(sort)` / `mongo(count)` | Eigenes `?sort=` bzw. `?count=1` — der Index kann das nicht garantieren | Erwartetes Verhalten; ohne `sort`/`count` messen | | `X-Search-Memory: mongo(sort)` / `mongo(count)` | Eigenes `?sort=` bzw. `?count=1` — der Index kann das nicht garantieren | Erwartetes Verhalten; ohne `sort`/`count` messen |
| `X-Search-Memory: mongo(lookup)` / `mongo(aggregate)` / `mongo(hook-pipeline)` | Anfrage nutzt Schritte, die in der MongoDB-Pipeline laufen | Erwartetes Verhalten; ohne `lookup`/`aggregate`-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 Suche wirkungslos | Facetten sind eigene Route (`…/_facet`) | [Lesen und suchen](/projekt/abfragen-lesen/) beachten |