electric-horses-infra/stacks/eh-search/app/schemas.py

83 lines
1.7 KiB
Python
Raw Permalink Normal View History

"""Pydantic response models."""
from pydantic import BaseModel, Field
from typing import Literal, Any
IntentType = Literal[
"komm_nr",
"dvn",
"vin",
"autocomplete_only",
"keyword_search",
"empty",
]
ResultType = Literal["vehicle", "page", "blog", "brand"]
class SearchResultItem(BaseModel):
"""Unified result item — fields are optional depending on type."""
type: ResultType = "vehicle"
title: str
slug: str | None = None
snippet: str | None = None
score: float = 0.0
matched_via: str = ""
# Vehicle-specific
vehicle_id: int | None = None
commission_number: str | None = None
vin: str | None = None
brand: str | None = None
model: str | None = None
price: float | None = None
primary_image_id: str | None = None
directus_product_id: int | None = None
# Blog-specific
tags: list[str] | None = None
category: str | None = None
published_at: str | None = None
image_id: str | None = None
# Brand-specific
logo_id: str | None = None
model_config = {"extra": "allow"}
class SearchResponse(BaseModel):
query: str
intent: IntentType
direct_redirect: bool = False
total: int
results: list[SearchResultItem]
took_ms: int
cache_hit: bool = False
class SuggestItem(BaseModel):
text: str
type: Literal["brand", "model", "category"]
count: int = 0
class SuggestResponse(BaseModel):
query: str
suggestions: list[SuggestItem]
took_ms: int
class HealthResponse(BaseModel):
status: str
environment: str
db: str
redis: str
vehicles_count: int
content: dict[str, Any] = Field(default_factory=dict)
class InvalidateResponse(BaseModel):
cleared: int
scope: str = "all"