@@ -88,7 +88,7 @@ class DistanceStrategy(str, enum.Enum):
8888 "$ilike" ,
8989}
9090
91- LOGICAL_OPERATORS = {"$and" , "$or" }
91+ LOGICAL_OPERATORS = {"$and" , "$or" , "$not" }
9292
9393SUPPORTED_OPERATORS = (
9494 set (COMPARISONS_TO_NATIVE )
@@ -1248,26 +1248,25 @@ def _create_filter_clause(self, filters: Any) -> Any:
12481248 """
12491249 if isinstance (filters , dict ):
12501250 if len (filters ) == 1 :
1251- # The only operators allowed at the top level are $AND and $OR
1251+ # The only operators allowed at the top level are $AND, $OR, and $NOT
12521252 # First check if an operator or a field
12531253 key , value = list (filters .items ())[0 ]
12541254 if key .startswith ("$" ):
12551255 # Then it's an operator
1256- if key .lower () not in ["$and" , "$or" ]:
1256+ if key .lower () not in ["$and" , "$or" , "$not" ]:
12571257 raise ValueError (
1258- f"Invalid filter condition. Expected $and or $or "
1258+ f"Invalid filter condition. Expected $and, $ or or $not "
12591259 f"but got: { key } "
12601260 )
12611261 else :
12621262 # Then it's a field
12631263 return self ._handle_field_filter (key , filters [key ])
12641264
1265- # Here we handle the $and and $or operators
1266- if not isinstance (value , list ):
1267- raise ValueError (
1268- f"Expected a list, but got { type (value )} for value: { value } "
1269- )
12701265 if key .lower () == "$and" :
1266+ if not isinstance (value , list ):
1267+ raise ValueError (
1268+ f"Expected a list, but got { type (value )} for value: { value } "
1269+ )
12711270 and_ = [self ._create_filter_clause (el ) for el in value ]
12721271 if len (and_ ) > 1 :
12731272 return sqlalchemy .and_ (* and_ )
@@ -1279,6 +1278,10 @@ def _create_filter_clause(self, filters: Any) -> Any:
12791278 "but got an empty dictionary"
12801279 )
12811280 elif key .lower () == "$or" :
1281+ if not isinstance (value , list ):
1282+ raise ValueError (
1283+ f"Expected a list, but got { type (value )} for value: { value } "
1284+ )
12821285 or_ = [self ._create_filter_clause (el ) for el in value ]
12831286 if len (or_ ) > 1 :
12841287 return sqlalchemy .or_ (* or_ )
@@ -1289,9 +1292,29 @@ def _create_filter_clause(self, filters: Any) -> Any:
12891292 "Invalid filter condition. Expected a dictionary "
12901293 "but got an empty dictionary"
12911294 )
1295+ elif key .lower () == "$not" :
1296+ if isinstance (value , list ):
1297+ not_conditions = [
1298+ self ._create_filter_clause (item ) for item in value
1299+ ]
1300+ not_ = sqlalchemy .and_ (
1301+ * [
1302+ sqlalchemy .not_ (condition )
1303+ for condition in not_conditions
1304+ ]
1305+ )
1306+ return not_
1307+ elif isinstance (value , dict ):
1308+ not_ = self ._create_filter_clause (value )
1309+ return sqlalchemy .not_ (not_ )
1310+ else :
1311+ raise ValueError (
1312+ f"Invalid filter condition. Expected a dictionary "
1313+ f"or a list but got: { type (value )} "
1314+ )
12921315 else :
12931316 raise ValueError (
1294- f"Invalid filter condition. Expected $and or $or "
1317+ f"Invalid filter condition. Expected $and, $ or or $not "
12951318 f"but got: { key } "
12961319 )
12971320 elif len (filters ) > 1 :
0 commit comments