Skip to content

Commit

Permalink
library.py: search() - fts5 search improvement for keywords shorter t…
Browse files Browse the repository at this point in the history
…han 3 unicode characters

FTS5 'match' only evaluates substrings longer than 3 unicode characters, searching for
shorter substrings results in no matches being returned.

Fixes an issue where attempting to search for substrings shorter than 3 characters was
resulting in empty search results.

Add "AND description LIKE '%SUBSTRING%'" terms for each substring shorter than 3 characters.
  • Loading branch information
chmorgan authored and Bouni committed May 13, 2024
1 parent c37d15e commit 3c5c730
Showing 1 changed file with 30 additions and 7 deletions.
37 changes: 30 additions & 7 deletions library.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,18 +128,36 @@ def search(self, parameters):
query = f"SELECT {s} FROM parts WHERE "

match_chunks = []
like_chunks = []

query_chunks = []

# Build 'match_chunks' and 'like_chunks' arrays
#
# FTS5 (https://www.sqlite.org/fts5.html) has a substring limit of
# at least 3 characters.
# 'Substrings consisting of fewer than 3 unicode characters do not
# match any rows when used with a full-text query'
#
# However, they will still match with a LIKE.
#
# So extract out the <3 character strings and add a 'LIKE' term
# for each of those.
if parameters["keyword"] != "":
keywords = parameters["keyword"].split(" ")
keywords_intermediate = []
match_keywords_intermediate = []
for w in keywords:
# skip over empty keywords
if w != "":
kw = f'"{w}"'
keywords_intermediate.append(kw)
keywords_entry = " AND ".join(keywords_intermediate)
match_chunks.append(f"{keywords_entry}")
if len(w) < 3: # LIKE entry
kw = f"description LIKE '%{w}%'"
like_chunks.append(kw)
else: # MATCH entry
kw = f'"{w}"'
match_keywords_intermediate.append(kw)
if match_keywords_intermediate:
match_entry = " AND ".join(match_keywords_intermediate)
match_chunks.append(f"{match_entry}")

if "manufacturer" in parameters and parameters["manufacturer"] != "":
p = parameters["manufacturer"]
Expand Down Expand Up @@ -171,17 +189,22 @@ def search(self, parameters):
if parameters["stock"]:
query_chunks.append('"Stock" > "0"')

if not match_chunks and not query_chunks:
if not match_chunks and not like_chunks and not query_chunks:
return []

if match_chunks:
query += "parts MATCH '"
query += " AND ".join(match_chunks)
query += "'"

if query_chunks:
if like_chunks:
if match_chunks:
query += " AND "
query += " AND ".join(like_chunks)

if query_chunks:
if match_chunks or like_chunks:
query += " AND "
query += " AND ".join(query_chunks)

query += f' ORDER BY "{self.order_by}" COLLATE naturalsort {self.order_dir}'
Expand Down

0 comments on commit 3c5c730

Please sign in to comment.