@@ -51,12 +51,12 @@ class FilterKey(enum.IntEnum):
51
51
DUPLICATED = 5
52
52
53
53
54
- class AttrHint (TypedDict ):
54
+ class AttrHint (BaseModel ):
55
55
name : str
56
- is_readable : NotRequired [ bool ]
57
- filter_key : NotRequired [ FilterKey ]
58
- keyword : NotRequired [ str ]
59
- exact_match : NotRequired [ bool ]
56
+ is_readable : bool | None = None
57
+ filter_key : FilterKey | None = None
58
+ keyword : str | None = None
59
+ exact_match : bool | None = None
60
60
61
61
62
62
class AttributeDocument (TypedDict ):
@@ -267,23 +267,23 @@ def make_query(
267
267
268
268
# Conversion processing from "filter_key" to "keyword" for each hint_attrs
269
269
for hint_attr in hint_attrs :
270
- match hint_attr .get ( " filter_key" , None ) :
270
+ match hint_attr .filter_key :
271
271
case FilterKey .CLEARED :
272
272
# remove "keyword" parameter
273
- hint_attr .pop ( " keyword" , None )
273
+ hint_attr .keyword = None
274
274
case FilterKey .EMPTY :
275
- hint_attr [ " keyword" ] = "\\ "
275
+ hint_attr . keyword = "\\ "
276
276
case FilterKey .NON_EMPTY :
277
- hint_attr [ " keyword" ] = "*"
277
+ hint_attr . keyword = "*"
278
278
case FilterKey .DUPLICATED :
279
- aggs_query = _make_aggs_query (hint_attr [ " name" ] )
279
+ aggs_query = _make_aggs_query (hint_attr . name )
280
280
# TODO Set to 1 for convenience
281
281
resp = execute_query (aggs_query , 1 )
282
282
keyword_infos = resp ["aggregations" ]["attr_aggs" ]["attr_name_aggs" ][
283
283
"attr_value_aggs"
284
284
]["buckets" ]
285
285
keyword_list = [x ["key" ] for x in keyword_infos ]
286
- hint_attr [ " keyword" ] = CONFIG .OR_SEARCH_CHARACTER .join (
286
+ hint_attr . keyword = CONFIG .OR_SEARCH_CHARACTER .join (
287
287
["^" + x + "$" for x in keyword_list ]
288
288
)
289
289
@@ -324,9 +324,7 @@ def make_query(
324
324
"query" : {
325
325
"bool" : {
326
326
"should" : [
327
- {"term" : {"attr.name" : x ["name" ]}}
328
- for x in hint_attrs
329
- if "name" in x
327
+ {"term" : {"attr.name" : x .name }} for x in hint_attrs if x .name
330
328
]
331
329
}
332
330
},
@@ -337,7 +335,7 @@ def make_query(
337
335
attr_query : dict [str , dict ] = {}
338
336
339
337
# filter attribute by keywords
340
- for hint in [hint for hint in hint_attrs if " name" in hint and hint .get ( " keyword" ) ]:
338
+ for hint in [hint for hint in hint_attrs if hint . name and hint .keyword ]:
341
339
attr_query .update (_parse_or_search (hint ))
342
340
343
341
# Build queries along keywords
@@ -649,7 +647,7 @@ def _parse_or_search(hint: AttrHint) -> dict[str, dict]:
649
647
duplicate_keys : list = []
650
648
651
649
# Split and process keywords with 'or'
652
- for keyword_divided_or in hint [ " keyword" ] .split (CONFIG .OR_SEARCH_CHARACTER ):
650
+ for keyword_divided_or in ( hint . keyword or "" ) .split (CONFIG .OR_SEARCH_CHARACTER ):
653
651
parsed_query = _parse_and_search (hint , keyword_divided_or , duplicate_keys )
654
652
attr_query .update (parsed_query )
655
653
@@ -696,7 +694,7 @@ def _parse_and_search(
696
694
697
695
# Keyword divided by 'or' is processed by dividing by 'and'
698
696
for keyword in keyword_divided_or .split (CONFIG .AND_SEARCH_CHARACTER ):
699
- key = f"{ keyword } _{ hint [ ' name' ] } "
697
+ key = f"{ keyword } _{ hint . name } "
700
698
701
699
# Skip if keywords overlap
702
700
if key in duplicate_keys :
@@ -742,29 +740,29 @@ def _build_queries_along_keywords(
742
740
"""
743
741
744
742
# Get the keyword.
745
- hints = [x for x in hint_attrs if "keyword" in x and x [ " keyword" ] ]
743
+ hints = [x for x in hint_attrs if x . keyword ]
746
744
res_query : dict [str , Any ] = {}
747
745
748
746
for hint in hints :
749
747
and_query : dict [str , Any ] = {}
750
748
or_query : dict [str , Any ] = {}
751
749
752
750
# Split keyword by 'or'
753
- for keyword_divided_or in hint [ " keyword" ] .split (CONFIG .OR_SEARCH_CHARACTER ):
751
+ for keyword_divided_or in ( hint . keyword or "" ) .split (CONFIG .OR_SEARCH_CHARACTER ):
754
752
if CONFIG .AND_SEARCH_CHARACTER in keyword_divided_or :
755
753
# If 'AND' is included in the keyword divided by 'OR', add it to 'filter'
756
754
for keyword in keyword_divided_or .split (CONFIG .AND_SEARCH_CHARACTER ):
757
755
if keyword_divided_or not in and_query :
758
756
and_query [keyword_divided_or ] = {"bool" : {"filter" : []}}
759
757
760
758
and_query [keyword_divided_or ]["bool" ]["filter" ].append (
761
- attr_query [keyword + "_" + hint [ " name" ] ]
759
+ attr_query [keyword + "_" + hint . name ]
762
760
)
763
761
764
762
else :
765
- and_query [keyword_divided_or ] = attr_query [keyword_divided_or + "_" + hint [ " name" ] ]
763
+ and_query [keyword_divided_or ] = attr_query [keyword_divided_or + "_" + hint . name ]
766
764
767
- if CONFIG .OR_SEARCH_CHARACTER in hint [ " keyword" ] :
765
+ if CONFIG .OR_SEARCH_CHARACTER in ( hint . keyword or "" ) :
768
766
# If the keyword contains 'or', concatenate with 'should'
769
767
if not or_query :
770
768
or_query = {"bool" : {"should" : []}}
@@ -817,7 +815,7 @@ def _make_an_attribute_filter(hint: AttrHint, keyword: str) -> dict[str, dict]:
817
815
dict[str, str]: Created attribute filter
818
816
819
817
"""
820
- cond_attr : list [dict ] = [{"term" : {"attr.name" : hint [ " name" ] }}]
818
+ cond_attr : list [dict ] = [{"term" : {"attr.name" : hint . name }}]
821
819
822
820
date_results = _is_date (keyword )
823
821
if date_results :
@@ -840,7 +838,7 @@ def _make_an_attribute_filter(hint: AttrHint, keyword: str) -> dict[str, dict]:
840
838
841
839
str_cond = {"regexp" : {"attr.value" : _get_regex_pattern (keyword )}}
842
840
843
- if hint .get ( " filter_key" ) == FilterKey .TEXT_NOT_CONTAINED :
841
+ if hint .filter_key == FilterKey .TEXT_NOT_CONTAINED :
844
842
cond_attr .append ({"bool" : {"must_not" : [date_cond , str_cond ]}})
845
843
else :
846
844
cond_attr .append ({"bool" : {"should" : [date_cond , str_cond ]}})
@@ -866,10 +864,10 @@ def _make_an_attribute_filter(hint: AttrHint, keyword: str) -> dict[str, dict]:
866
864
)
867
865
868
866
elif hint_keyword_val :
869
- if " exact_match" not in hint :
867
+ if hint . exact_match is None :
870
868
cond_val .append ({"regexp" : {"attr.value" : _get_regex_pattern (hint_keyword_val )}})
871
869
872
- if hint .get ( " filter_key" ) == FilterKey .TEXT_NOT_CONTAINED :
870
+ if hint .filter_key == FilterKey .TEXT_NOT_CONTAINED :
873
871
cond_attr .append ({"bool" : {"must_not" : cond_val }})
874
872
else :
875
873
cond_attr .append ({"bool" : {"should" : cond_val }})
@@ -1004,7 +1002,7 @@ def make_search_results(
1004
1002
# formalize attribute values according to the type
1005
1003
for attrinfo in entry_info ["attr" ]:
1006
1004
# Skip other than the target Attribute
1007
- if attrinfo ["name" ] not in [x [ " name" ] for x in hint_attrs ]:
1005
+ if attrinfo ["name" ] not in [x . name for x in hint_attrs ]:
1008
1006
continue
1009
1007
1010
1008
ret_attrinfo : AdvancedSearchResultRecordAttr = {}
@@ -1024,7 +1022,7 @@ def make_search_results(
1024
1022
record .attrs [attrinfo ["name" ]] = ret_attrinfo
1025
1023
1026
1024
# Check for has permission to EntityAttr
1027
- if attrinfo ["name" ] not in [x [ " name" ] for x in hint_attrs if x [ " is_readable" ] ]:
1025
+ if attrinfo ["name" ] not in [x . name for x in hint_attrs if x . is_readable ]:
1028
1026
ret_attrinfo ["is_readable" ] = False
1029
1027
continue
1030
1028
0 commit comments