Added backend support to perform exact matches

This commit is contained in:
Donkie
2024-05-25 20:53:48 +02:00
parent 65bfba89cf
commit b00075ab87
5 changed files with 66 additions and 16 deletions

View File

@@ -174,7 +174,8 @@ async def find(
title="Vendor Name", title="Vendor Name",
description=( description=(
"Partial case-insensitive search term for the filament vendor name. " "Partial case-insensitive search term for the filament vendor name. "
"Separate multiple terms with a comma. Specify an empty string to match filaments with no vendor name." "Separate multiple terms with a comma. Specify an empty string to match filaments with no vendor name. "
"Surround a term with quotes to search for the exact term."
), ),
), ),
vendor_id: Optional[str] = Query( vendor_id: Optional[str] = Query(
@@ -193,7 +194,8 @@ async def find(
title="Filament Name", title="Filament Name",
description=( description=(
"Partial case-insensitive search term for the filament name. Separate multiple terms with a comma. " "Partial case-insensitive search term for the filament name. Separate multiple terms with a comma. "
"Specify an empty string to match filaments with no name." "Specify an empty string to match filaments with no name. "
"Surround a term with quotes to search for the exact term."
), ),
), ),
material: Optional[str] = Query( material: Optional[str] = Query(
@@ -201,7 +203,8 @@ async def find(
title="Filament Material", title="Filament Material",
description=( description=(
"Partial case-insensitive search term for the filament material. Separate multiple terms with a comma. " "Partial case-insensitive search term for the filament material. Separate multiple terms with a comma. "
"Specify an empty string to match filaments with no material." "Specify an empty string to match filaments with no material. "
"Surround a term with quotes to search for the exact term."
), ),
), ),
article_number: Optional[str] = Query( article_number: Optional[str] = Query(
@@ -210,7 +213,8 @@ async def find(
description=( description=(
"Partial case-insensitive search term for the filament article number. " "Partial case-insensitive search term for the filament article number. "
"Separate multiple terms with a comma. " "Separate multiple terms with a comma. "
"Specify an empty string to match filaments with no article number." "Specify an empty string to match filaments with no article number. "
"Surround a term with quotes to search for the exact term."
), ),
), ),
color_hex: Optional[str] = Query( color_hex: Optional[str] = Query(
@@ -231,7 +235,8 @@ async def find(
description=( description=(
"Find filaments imported by the given external ID. " "Find filaments imported by the given external ID. "
"Separate multiple IDs with a comma. " "Separate multiple IDs with a comma. "
"Specify empty string to match filaments with no external ID." "Specify empty string to match filaments with no external ID. "
"Surround a term with quotes to search for the exact term."
), ),
example="polymaker_pla_polysonicblack_1000_175", example="polymaker_pla_polysonicblack_1000_175",
), ),

View File

@@ -170,8 +170,9 @@ async def find(
default=None, default=None,
title="Filament Name", title="Filament Name",
description=( description=(
"Partial case-insensitive search term for the filament name. Separate multiple terms with a comma." "Partial case-insensitive search term for the filament name. Separate multiple terms with a comma. "
" Specify an empty string to match spools with no filament name." "Specify an empty string to match spools with no filament name. "
"Surround a term with quotes to search for the exact term."
), ),
), ),
filament_id: Optional[str] = Query( filament_id: Optional[str] = Query(
@@ -188,7 +189,8 @@ async def find(
title="Filament Material", title="Filament Material",
description=( description=(
"Partial case-insensitive search term for the filament material. Separate multiple terms with a comma. " "Partial case-insensitive search term for the filament material. Separate multiple terms with a comma. "
"Specify an empty string to match spools with no filament material." "Specify an empty string to match spools with no filament material. "
"Surround a term with quotes to search for the exact term."
), ),
), ),
filament_vendor_name: Optional[str] = Query( filament_vendor_name: Optional[str] = Query(
@@ -197,7 +199,8 @@ async def find(
title="Vendor Name", title="Vendor Name",
description=( description=(
"Partial case-insensitive search term for the filament vendor name. Separate multiple terms with a comma. " "Partial case-insensitive search term for the filament vendor name. Separate multiple terms with a comma. "
"Specify an empty string to match spools with no vendor name." "Specify an empty string to match spools with no vendor name. "
"Surround a term with quotes to search for the exact term."
), ),
), ),
filament_vendor_id: Optional[str] = Query( filament_vendor_id: Optional[str] = Query(
@@ -216,7 +219,8 @@ async def find(
title="Location", title="Location",
description=( description=(
"Partial case-insensitive search term for the spool location. Separate multiple terms with a comma. " "Partial case-insensitive search term for the spool location. Separate multiple terms with a comma. "
"Specify an empty string to match spools with no location." "Specify an empty string to match spools with no location. "
"Surround a term with quotes to search for the exact term."
), ),
), ),
lot_nr: Optional[str] = Query( lot_nr: Optional[str] = Query(
@@ -224,7 +228,8 @@ async def find(
title="Lot/Batch Number", title="Lot/Batch Number",
description=( description=(
"Partial case-insensitive search term for the spool lot number. Separate multiple terms with a comma. " "Partial case-insensitive search term for the spool lot number. Separate multiple terms with a comma. "
"Specify an empty string to match spools with no lot nr." "Specify an empty string to match spools with no lot nr. "
"Surround a term with quotes to search for the exact term."
), ),
), ),
allow_archived: bool = Query( allow_archived: bool = Query(

View File

@@ -83,7 +83,10 @@ async def find(
name: Optional[str] = Query( name: Optional[str] = Query(
default=None, default=None,
title="Vendor Name", title="Vendor Name",
description="Partial case-insensitive search term for the vendor name. Separate multiple terms with a comma.", description=(
"Partial case-insensitive search term for the vendor name. Separate multiple terms with a comma. "
"Surround a term with quotes to search for the exact term."
),
), ),
external_id: Optional[str] = Query( external_id: Optional[str] = Query(
default=None, default=None,
@@ -91,7 +94,8 @@ async def find(
description=( description=(
"Exact match for the vendor external ID. " "Exact match for the vendor external ID. "
"Separate multiple IDs with a comma. " "Separate multiple IDs with a comma. "
"Specify empty string to match filaments with no external ID." "Specify empty string to match filaments with no external ID. "
"Surround a term with quotes to search for the exact term."
), ),
), ),
sort: Optional[str] = Query( sort: Optional[str] = Query(

View File

@@ -47,9 +47,14 @@ def add_where_clause_str_opt(
if value is not None: if value is not None:
conditions = [] conditions = []
for value_part in value.split(","): for value_part in value.split(","):
# If part is empty, search for empty fields
if len(value_part) == 0: if len(value_part) == 0:
conditions.append(field.is_(None)) conditions.append(field.is_(None))
conditions.append(field == "") conditions.append(field == "")
# Do exact match if value_part is surrounded by quotes
elif value_part[0] == '"' and value_part[-1] == '"':
conditions.append(field == value_part[1:-1])
# Do fuzzy match if value_part is not surrounded by quotes
else: else:
conditions.append(field.ilike(f"%{value_part}%")) conditions.append(field.ilike(f"%{value_part}%"))
@@ -66,8 +71,13 @@ def add_where_clause_str(
if value is not None: if value is not None:
conditions = [] conditions = []
for value_part in value.split(","): for value_part in value.split(","):
# If part is empty, search for empty fields
if len(value_part) == 0: if len(value_part) == 0:
conditions.append(field == "") conditions.append(field == "")
# Do exact match if value_part is surrounded by quotes
elif value_part[0] == '"' and value_part[-1] == '"':
conditions.append(field == value_part[1:-1])
# Do fuzzy match if value_part is not surrounded by quotes
else: else:
conditions.append(field.ilike(f"%{value_part}%")) conditions.append(field.ilike(f"%{value_part}%"))

View File

@@ -61,7 +61,7 @@ def filaments(random_vendor_mod: dict[str, Any], random_empty_vendor_mod: dict[s
f"{URL}/api/v1/filament", f"{URL}/api/v1/filament",
json={ json={
"name": "Filament Z", "name": "Filament Z",
"material": "PETG", "material": "PLA+",
"price": 200, "price": 200,
"density": 1.25, "density": 1.25,
"diameter": 1.75, "diameter": 1.75,
@@ -256,7 +256,20 @@ def test_find_filaments_by_name(filaments: Fixture):
# Execute # Execute
result = httpx.get( result = httpx.get(
f"{URL}/api/v1/filament", f"{URL}/api/v1/filament",
params={"name": "Filament X"}, params={"name": "Filament"},
)
result.raise_for_status()
# Verify
filaments_result = result.json()
assert_lists_compatible(filaments_result, filaments.filaments[:3])
def test_find_filaments_by_exact_name(filaments: Fixture):
# Execute
result = httpx.get(
f"{URL}/api/v1/filament",
params={"name": '"Filament X"'},
) )
result.raise_for_status() result.raise_for_status()
@@ -301,7 +314,20 @@ def test_find_filaments_by_multiple_materials(filaments: Fixture):
# Verify # Verify
filaments_result = result.json() filaments_result = result.json()
assert_lists_compatible(filaments_result, filaments.filaments[:2]) assert_lists_compatible(filaments_result, filaments.filaments[:3])
def test_find_filaments_by_exact_material(filaments: Fixture):
# Execute
result = httpx.get(
f"{URL}/api/v1/filament",
params={"material": '"PLA"'},
)
result.raise_for_status()
# Verify
filaments_result = result.json()
assert_lists_compatible(filaments_result, filaments.filaments[:1])
def test_find_filaments_by_empty_material(filaments: Fixture): def test_find_filaments_by_empty_material(filaments: Fixture):