-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsearch_dto.py
More file actions
59 lines (40 loc) · 1.64 KB
/
Copy pathsearch_dto.py
File metadata and controls
59 lines (40 loc) · 1.64 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
from __future__ import annotations
from typing import Annotated, List, Literal, Optional, Union
from pydantic import BaseModel, Field, model_validator
from app.schemas.paper_dto import PaperDto
class TextCondition(BaseModel):
"""Single text-based filter condition on a paper field."""
type: Literal["condition"]
field: Literal["title", "abstract"]
operator: Literal["contains", "not_contains"]
value: str
class ConditionGroup(BaseModel):
"""Logical group combining multiple conditions with AND / OR."""
type: Literal["group"]
operator: Literal["AND", "OR"]
children: List[
Annotated[Union[TextCondition, ConditionGroup], Field(discriminator="type")]
]
class AdvancedSearchFilter(BaseModel):
"""Structured filter with optional year range and boolean condition tree."""
year_from: Optional[int] = Field(default=None, ge=1, le=9999)
year_to: Optional[int] = Field(default=None, ge=1, le=9999)
root: ConditionGroup
@model_validator(mode="after")
def check_year_range(self) -> AdvancedSearchFilter:
"""Validate year_from is larger or equal to year_to."""
if self.year_from is not None and self.year_to is not None:
if self.year_from > self.year_to:
raise ValueError("year_from must be <= year_to")
return self
class SearchRequest(BaseModel):
"""
Request to search for specified query
"""
query: str
filter: Optional[AdvancedSearchFilter] = None
class SearchResponse(BaseModel):
"""
Response to search for specified query
"""
papers: List[PaperDto]