optimize search query

This commit is contained in:
MuslemRahimi 2024-12-13 19:58:50 +01:00
parent d3d68cb1e6
commit 3af2299cdf

View File

@ -63,33 +63,27 @@ def calculate_score(item: Dict, search_query: str) -> int:
name_lower = item['name'].lower() name_lower = item['name'].lower()
symbol_lower = item['symbol'].lower() symbol_lower = item['symbol'].lower()
query_lower = search_query.lower() query_lower = search_query.lower()
# Exact symbol match # Base priority calculations
if symbol_lower == query_lower: if symbol_lower == query_lower:
return PRIORITY_STRATEGIES['exact_symbol_match'] base_score = PRIORITY_STRATEGIES['exact_symbol_match']
elif symbol_lower.startswith(query_lower):
# Symbol prefix match base_score = PRIORITY_STRATEGIES['symbol_prefix_match']
if symbol_lower.startswith(query_lower): elif name_lower == query_lower:
return PRIORITY_STRATEGIES['symbol_prefix_match'] base_score = PRIORITY_STRATEGIES['exact_name_match']
elif name_lower.startswith(query_lower):
# Exact name match base_score = PRIORITY_STRATEGIES['name_prefix_match']
if name_lower == query_lower: elif query_lower in symbol_lower:
return PRIORITY_STRATEGIES['exact_name_match'] base_score = PRIORITY_STRATEGIES['symbol_contains']
elif query_lower in name_lower:
# Name prefix match base_score = PRIORITY_STRATEGIES['name_contains']
if name_lower.startswith(query_lower): else:
return PRIORITY_STRATEGIES['name_prefix_match'] base_score = len(PRIORITY_STRATEGIES)
# Symbol contains query # Apply penalty if the symbol contains a dot
if query_lower in symbol_lower: dot_penalty = 1 if '.' in symbol_lower else 0
return PRIORITY_STRATEGIES['symbol_contains']
return base_score + dot_penalty
# Name contains query
if query_lower in name_lower:
return PRIORITY_STRATEGIES['name_contains']
# Fallback
return len(PRIORITY_STRATEGIES)
@contextmanager @contextmanager
@ -116,13 +110,14 @@ with db_connection(STOCK_DB) as cursor:
cursor.execute("SELECT DISTINCT symbol FROM stocks") cursor.execute("SELECT DISTINCT symbol FROM stocks")
symbols = [row[0] for row in cursor.fetchall()] symbols = [row[0] for row in cursor.fetchall()]
cursor.execute("SELECT symbol, name, type FROM stocks") cursor.execute("SELECT symbol, name, type, marketCap FROM stocks")
raw_data = cursor.fetchall() raw_data = cursor.fetchall()
stock_list_data = [{ stock_list_data = [{
'symbol': row[0], 'symbol': row[0],
'name': row[1], 'name': row[1],
'type': row[2].capitalize(), 'type': row[2].capitalize(),
} for row in raw_data] 'marketCap': row[3],
} for row in raw_data if row[3] is not None]
#------End Stocks DB------------# #------End Stocks DB------------#
#------Start ETF DB------------# #------Start ETF DB------------#
@ -1804,17 +1799,24 @@ async def get_stock(
# Precompile case-insensitive regex for faster matching # Precompile case-insensitive regex for faster matching
search_pattern = re.compile(re.escape(query.lower()), re.IGNORECASE) search_pattern = re.compile(re.escape(query.lower()), re.IGNORECASE)
# Optimized filtering and sorting
results = sorted(
(
item for item in searchbar_data
if search_pattern.search(item['name']) or search_pattern.search(item['symbol'])
),
key=lambda item: calculate_score(item, query)
)[:5]
return JSONResponse(content=orjson.loads(orjson.dumps(results)))
# Filter items based on the search pattern (ignore items where neither name nor symbol match)
filtered_data = [
item for item in searchbar_data
if search_pattern.search(item['name']) or search_pattern.search(item['symbol'])
]
# Sort by the calculated score, giving exact symbol matches the highest priority,
# and then by descending marketCap for other matches
results = sorted(
filtered_data,
key=lambda item: (
calculate_score(item, query),
0 if item.get('marketCap') is None else -item['marketCap']
)
)[:5]
return JSONResponse(content=orjson.loads(orjson.dumps(results)))