search.py
3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
"""
Search API routes.
"""
from fastapi import APIRouter, HTTPException, Query
from typing import Optional
from ..models import (
SearchRequest,
ImageSearchRequest,
SearchResponse,
DocumentResponse,
ErrorResponse
)
router = APIRouter(prefix="/search", tags=["search"])
@router.post("/", response_model=SearchResponse)
async def search(request: SearchRequest):
"""
Execute text search query.
Supports:
- Multi-language query processing
- Boolean operators (AND, OR, RANK, ANDNOT)
- Semantic search with embeddings
- Custom ranking functions
- Filters and aggregations
"""
from fastapi import Request as FastAPIRequest
req: FastAPIRequest = None
try:
# Get searcher from app state
from main import get_searcher
searcher = get_searcher()
# Execute search
result = searcher.search(
query=request.query,
size=request.size,
from_=request.from_,
filters=request.filters,
enable_translation=request.enable_translation,
enable_embedding=request.enable_embedding,
enable_rerank=request.enable_rerank,
min_score=request.min_score
)
# Convert to response model
return SearchResponse(
hits=result.hits,
total=result.total,
max_score=result.max_score,
took_ms=result.took_ms,
aggregations=result.aggregations,
query_info=result.query_info
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/image", response_model=SearchResponse)
async def search_by_image(request: ImageSearchRequest):
"""
Search by image similarity.
Uses image embeddings to find visually similar products.
"""
try:
from main import get_searcher
searcher = get_searcher()
# Execute image search
result = searcher.search_by_image(
image_url=request.image_url,
size=request.size,
filters=request.filters
)
return SearchResponse(
hits=result.hits,
total=result.total,
max_score=result.max_score,
took_ms=result.took_ms,
aggregations=result.aggregations,
query_info=result.query_info
)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/{doc_id}", response_model=DocumentResponse)
async def get_document(doc_id: str):
"""
Get a single document by ID.
"""
try:
from main import get_searcher
searcher = get_searcher()
doc = searcher.get_document(doc_id)
if doc is None:
raise HTTPException(status_code=404, detail=f"Document {doc_id} not found")
return DocumentResponse(id=doc_id, source=doc)
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))