electric-horses-infra/stacks/eh-search/Agent.md
Benjamin Weinlich b3813ed6ac feat(stacks/eh-search): add site-search FastAPI service
Mirrors /opt/ai-apps/eh-search/ on the server, including the full
FastAPI app (intent routing, FTS+fuzzy+substring hybrid, multi-source
federation across vehicles + blog + brands + pages + static + tag
bridge), SQL schema (Postgres materialized view with german_unaccent
text search, pg_trgm for fuzzy), Dockerfile and compose.

Sanitized the hardcoded password in sql/01_init.sql — replaced with
REPLACE_ME_BEFORE_APPLYING placeholder since this repo is public.

The eh-search service binds only on the private network (10.0.0.8:8200)
and is reachable only via Pegasus nginx proxy at /api/search.

Refs OP#1094 OP#1105 OP#1112 OP#1116 OP#1117
2026-04-11 22:19:39 +02:00

3 KiB

Agent Briefing — eh-search Stack

Du arbeitest am Site-Search-Service von electric-horses.de. Lies erst ../../Agent.md am Repo-Root für globale Konventionen.

Ein FastAPI-basierter Suchservice für die Electric-Horses-Website. Unterstützt:

  • Exact Lookup via Kommissionsnummer (z.B. D9094) und DVN (z.B. 9094)
  • Full-Text Search (Postgres ts_vector mit german_unaccent Dictionary)
  • Fuzzy Search (pg_trgm Trigramm-Matching)
  • Multi-Source Federation: Vehicles + Blog-Posts + Brands + Pages + Static Pages + Tag-Bridge
  • Cmd+K Command Palette im Astro-Frontend, mit Silent-SSO-Style "Öffnet sich bei Tastendruck"

Live-Deployment

  • Server: ai-apps (Hetzner cx22, 10.0.0.8 privat)
  • Pfad: /opt/ai-apps/eh-search/
  • Binding: NUR 10.0.0.8:8200 (privat), NICHT public. Wird über Pegasus Nginx via /api/search erreicht.
  • Frontend-Integration: Astro Command-Palette auf electric-horses.de + dev.electric-horses.de
  • Content-Hosting: Der Suchindex nutzt die Postgres-DB eh_vehicles (Schema in sql/), ein In-Memory Content-Index (aus Directus gezogen), und hardcoded Static Pages + Tag-Bridge.

Architektur-Verweis

  • Datenquelle für Fahrzeuge: PostgreSQL eh_vehicles auf loco-replica-db (privater Postgres 17 Container)
  • Datenquelle für Blog/Brands/Pages: Directus REST API auf Pegasus (10.0.0.10:8055)
  • Cache: Redis (dediziert im Stack)
  • Intent Routing: Regex-basiert, siehe app/intent_router.py
  • Zwei Komm-Nr-Konzepte in Loco-Soft: (a) Kundenseitig {type_letter}{dvn} z.B. D9094, (b) interne Fahrzeug-Nummer. Nur (a) der Kunde jemals sehen. Siehe Memory project_eh_search_phase1.md.

Kritische Files

  • app/main.py — FastAPI Entry + Endpoint-Definitionen
  • app/intent_router.py — Query → Intent (komm_nr, dvn, keyword_search, ...)
  • app/search/exact.py — Exact Lookup (Komm-Nr, DVN, VIN)
  • app/search/fts.py — FTS + Fuzzy + Substring Fallback + Hybrid
  • app/search/static_pages.py — Static Page Registry + Tag→Page Bridge (~60 Mappings)
  • app/content_index.py — In-Memory Index aus Directus (Blog, Brands, Pages)
  • app/schemas.py — Pydantic-Response-Models
  • sql/01_init.sql — Initial Postgres Setup (pg_trgm, MView, search_read user)
  • sql/02_komm_nr_fix.sql — Komm-Nr Datenmodell-Korrektur

Ops-Kommandos

ssh ai-apps
cd /opt/ai-apps/eh-search

# Rebuild & restart nach Code-Änderung
docker compose up -d --build eh-search

# Cache invalidieren
curl -X POST http://10.0.0.8:8200/cache/invalidate

# Health
curl -s http://10.0.0.8:8200/health | jq .

# Logs
docker logs eh-search --tail 30

OpenProject

  • M6 — Site Search Phase 1 (abgeschlossen)
  • M6.2 — Federated Multi-Source (abgeschlossen)
  • M6.3 — UX Refinement (abgeschlossen)
  • M6.4 — Komm-Nr Datenmodell-Fix (abgeschlossen)
  • M6.5 — Sync-Fix für Deaktivierungen (abgeschlossen)
  • Memory: project_eh_search_phase1.md — vollständige Historie und Gotchas
  • ../../Agent.md — Repo-weites Briefing