Blame view

api/routes/search.py 3.07 KB
be52af70   tangwang   first commit
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))