64 lines
2.8 KiB
Markdown
64 lines
2.8 KiB
Markdown
|
|
# eh-search — Site-Search für electric-horses.de
|
||
|
|
|
||
|
|
**Live:** Via Nginx-Proxy auf `https://www.electric-horses.de/api/search?q=...`
|
||
|
|
**Interne Adresse:** `http://10.0.0.8:8200` (privat, nicht public!)
|
||
|
|
**Stack-Pfad:** `/opt/ai-apps/eh-search/` auf ai-apps
|
||
|
|
|
||
|
|
## Was macht das?
|
||
|
|
Ein FastAPI-Service der eine **Cmd+K Command Palette** auf der Electric-Horses-Website mit Suchergebnissen versorgt. Durchsucht:
|
||
|
|
- 75 Fahrzeuge (Postgres FTS + Fuzzy + Komm-Nr/DVN Exact Lookup)
|
||
|
|
- 28 Blog-Posts (mit Tags + neue SEO-Descriptions)
|
||
|
|
- 24 Marken
|
||
|
|
- 6 Legal-Pages (Impressum, Datenschutz, ...)
|
||
|
|
- 8 Static Pages (Werkstatt, Ersatzteile, Kontakt, ...)
|
||
|
|
- 60 Tag → Page Bridges für semantische Verbindungen
|
||
|
|
|
||
|
|
**Killer-Feature:** Eingabe einer 4-stelligen Komm-Nr (oder `D9094` etc.) → Direct Redirect zur Fahrzeug-Detailseite. Latenz <50ms. Ideal für Mitarbeiter am Telefon.
|
||
|
|
|
||
|
|
## Architektur
|
||
|
|
```
|
||
|
|
Browser Cmd+K
|
||
|
|
↓
|
||
|
|
www.electric-horses.de/api/search
|
||
|
|
↓ (Nginx Proxy auf Pegasus)
|
||
|
|
10.0.0.8:8200 (eh-search auf ai-apps, privat)
|
||
|
|
↓
|
||
|
|
├─ Postgres eh_vehicles (loco-replica-db Container, Port 5433)
|
||
|
|
├─ Redis Cache (Stack-intern)
|
||
|
|
├─ Directus REST API (in-memory Content Index)
|
||
|
|
└─ Static Page Registry (hardcoded in Python)
|
||
|
|
```
|
||
|
|
|
||
|
|
## Sicherheit
|
||
|
|
- **Bind NUR auf privates Netz** (10.0.0.8:8200) — nicht über Public-IP erreichbar
|
||
|
|
- **Read-Only DB-User** (`search_read`) — kann nur SELECT auf Materialized View
|
||
|
|
- **Same-Origin via Pegasus Nginx** — kein CORS nötig, kein neues Cert, kein neues DNS
|
||
|
|
- **Rate Limit** via Nginx (30 req/s pro IP)
|
||
|
|
|
||
|
|
## Files
|
||
|
|
- `docker-compose.yml` — Stack
|
||
|
|
- `Dockerfile` — Python 3.12 + FastAPI + asyncpg + redis-py
|
||
|
|
- `requirements.txt` — Python-Deps
|
||
|
|
- `.env.example` — Template für `.env` (niemals echte `.env` committen!)
|
||
|
|
- `app/` — FastAPI-Anwendung
|
||
|
|
- `sql/` — Postgres-Schema und Migrations (search_vehicles Materialized View, pg_trgm, unaccent)
|
||
|
|
- `Agent.md` — AI-Briefing
|
||
|
|
- `README.md` — diese Datei
|
||
|
|
|
||
|
|
## Live-Update-Workflow
|
||
|
|
Wenn sich Fahrzeugdaten ändern (vehicle_sync.py nächtlich auf Pegasus), wird am Ende des Syncs automatisch die Materialized View refreshed UND der Redis-Cache invalidiert. Directus-Edits an Blog/Brands/Pages feuern einen Webhook an eh-search → sofortige Cache-Invalidation und Content-Index-Refresh.
|
||
|
|
|
||
|
|
## OpenProject Phasen (alle abgeschlossen)
|
||
|
|
- **M6** — Postgres FTS + Fuzzy + Exact + Command Palette (Phase 1)
|
||
|
|
- **M6.2** — Federated Multi-Source (Phase 1.5)
|
||
|
|
- **M6.3** — UX Refinement (sleek, mobile-first, smart group ordering)
|
||
|
|
- **M6.4** — Komm-Nr Datenmodell-Fix (D9094 korrekt statt falsche interne Nummer)
|
||
|
|
- **M6.5** — Sync-Fix für deaktivierte Fahrzeuge
|
||
|
|
|
||
|
|
## Out of Scope (mögliche Phase 2)
|
||
|
|
- Semantic Vector Search via Qdrant + bge-Embeddings
|
||
|
|
- Voice Input via Whisper
|
||
|
|
- LLM Filter-Extraktion via lokales Mistral/Gemma
|
||
|
|
- Image Search / OCR
|
||
|
|
- Cross-Encoder Reranking
|