From 089eae46a49a4d52c2711e81be81ffed6bf9ec53 Mon Sep 17 00:00:00 2001 From: white <122345776@umail.ucc.ie> Date: Thu, 6 Mar 2025 14:02:27 +0000 Subject: [PATCH 1/4] UPDATE: removed unused search routes --- web_server/blueprints/search_bar.py | 82 +---------------------------- 1 file changed, 1 insertion(+), 81 deletions(-) diff --git a/web_server/blueprints/search_bar.py b/web_server/blueprints/search_bar.py index 6d87397..2d1a1d6 100644 --- a/web_server/blueprints/search_bar.py +++ b/web_server/blueprints/search_bar.py @@ -55,84 +55,4 @@ def search_results(): print(query, streams, users, categories, flush=True) - return jsonify({"streams": streams, "categories": categories, "users": users}) - -@search_bp.route("/search/categories", methods=["GET", "POST"]) -def search_categories(): - """ - Display all the results for categories from the specified user query - """ - # Receive the query data from the user - data = request.get_json() - query = sanitize(data["query"]) - - # Create the connection to the database - db = Database() - db.create_connection() - - # Fetch the ranked data and send to JSON to be displayed - categories = db.fetchall(""" - SELECT bm25(category_fts) AS score, c.category_id, c.category_name - FROM categories AS c - INNER JOIN category_fts AS f ON c.category_id = f.category_id - WHERE f.category_name LIKE '%' || ? || '%' - ORDER BY score ASC; - """, (query,)) - - db.close_connection() - - return jsonify({"categories": categories}) - -@search_bp.route("/search/users", methods=["GET", "POST"]) -def search_users(): - """ - Display all the results for users from the specified user query - """ - # Receive the query data from the user - data = request.get_json() - query = sanitize(data["query"]) - - # Create the connection to the database - db = Database() - db.create_connection() - - # Fetch the ranked data and send to JSON to be displayed - users = db.fetchall(""" - SELECT bm25(user_fts) AS score, u.user_id, u.username, u.is_live - FROM users AS u - INNER JOIN user_fts AS f ON u.user_id = f.user_id - WHERE f.username LIKE '%' || ? || '%' - ORDER BY score ASC; - """, (query,)) - - db.close_connection() - - return jsonify({"users": users}) - - -@search_bp.route("/search/streams", methods=["GET", "POST"]) -def search_streams(): - """ - Display all the results for streams from the specified user query - """ - # Receive the query data from the user - data = request.get_json() - query = sanitize(data["query"]) - - # Create the connection to the database - db = Database() - db.create_connection() - - # Fetch the ranked data and send to JSON to be displayed - streams = db.fetchall(""" - SELECT bm25(stream_fts) AS score, s.user_id, s.title, s.num_viewers, s.category_id, u.username - FROM streams AS s - INNER JOIN stream_fts AS f ON s.user_id = f.user_id - INNER JOIN users AS u ON s.user_id = u.user_id - WHERE f.title LIKE '%' || ? || '%' - ORDER BY score ASC; - """, (query,)) - - db.close_connection() - - return jsonify({"streams": streams}) \ No newline at end of file + return jsonify({"streams": streams, "categories": categories, "users": users}) \ No newline at end of file From ead8573cb35d95d21b141696f69191d640af071a Mon Sep 17 00:00:00 2001 From: white <122345776@umail.ucc.ie> Date: Thu, 6 Mar 2025 16:44:29 +0000 Subject: [PATCH 2/4] UPDATE: removed virtual tables and triggers for fts --- web_server/database/app.db | Bin 167936 -> 167936 bytes web_server/database/text_search.sql | 114 ---------------------------- 2 files changed, 114 deletions(-) delete mode 100644 web_server/database/text_search.sql diff --git a/web_server/database/app.db b/web_server/database/app.db index 190741a9028fbae95d7d9fe0b9e86fd996c321a9..1182d484519cae20ec52a1cc2bcbccef648d3831 100644 GIT binary patch delta 4626 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 Kl%6_D^nU|E7c1wq&fzXJTQAjqHm<832A?$~xz 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 Date: Thu, 6 Mar 2025 16:45:46 +0000 Subject: [PATCH 3/4] FIX: made search algorithm work good --- web_server/blueprints/search_bar.py | 76 ++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/web_server/blueprints/search_bar.py b/web_server/blueprints/search_bar.py index 2d1a1d6..e853e7c 100644 --- a/web_server/blueprints/search_bar.py +++ b/web_server/blueprints/search_bar.py @@ -4,6 +4,26 @@ from utils.utils import sanitize search_bp = Blueprint("search", __name__) +def rank_results(query, result): + """ + Function that ranks results of queries. + + If word is an exact match, return 0 as score, + If character from search query are in something from the db, return score as 1, + Else return 2. + + Lower score means better search result. + """ + # Turn database result into iterative + charset = iter(result) + + # Assign a score based on the level of the match + if query in result: + return 0 + elif all(c in charset for c in query): + return 1 + return 2 + @search_bp.route("/search", methods=["POST"]) def search_results(): """ @@ -20,36 +40,46 @@ def search_results(): # Get the most accurate search results # 3 categories - categories = db.fetchall(""" - SELECT bm25(category_fts) AS score, c.category_id, c.category_name - FROM categories AS c - INNER JOIN category_fts AS f ON c.category_id = f.category_id - WHERE f.category_name LIKE '%' || ? || '%' - ORDER BY score ASC - LIMIT 4; - """, (query,)) + res_dict = [] + categories = db.fetchall("SELECT category_id, category_name FROM categories") + for c in categories: + key = c.get("category_name") + score = rank_results(query.lower(), key.lower()) + c["score"] = score + if score < 2: + res_dict.append(c) + categories = sorted(res_dict, key=lambda d: d["score"]) + categories = categories[:4] # 3 users - users = db.fetchall(""" - SELECT bm25(user_fts) AS score, u.user_id, u.username, u.is_live - FROM users AS u - INNER JOIN user_fts AS f ON u.user_id = f.user_id - WHERE f.username LIKE '%' || ? || '%' - ORDER BY score ASC - LIMIT 4; - """, (query,)) + res_dict = [] + users = db.fetchall("SELECT user_id, username, is_live FROM users") + for u in users: + key = u.get("username") + score = rank_results(query, key) + u["score"] = score + if score < 2: + res_dict.append(u) + users = sorted(res_dict, key=lambda d: d["score"]) + users = users[:4] - # 3 streams - streams = db.fetchall(""" - SELECT bm25(stream_fts) AS score, s.user_id, s.title, s.num_viewers, c.category_name, u.username + # 3 streams + res_dict = [] + streams = db.fetchall("""SELECT s.user_id, s.title, s.num_viewers, c.category_name, u.username FROM streams AS s INNER JOIN stream_fts AS f ON s.user_id = f.user_id INNER JOIN users AS u ON s.user_id = u.user_id INNER JOIN categories AS c ON s.category_id = c.category_id - WHERE f.title LIKE '%' || ? || '%' - ORDER BY score ASC - LIMIT 4; - """, (query,)) + """) + + for s in streams: + key = s.get("username") + score = rank_results(query, key) + s["score"] = score + if score < 2: + res_dict.append(s) + streams = sorted(res_dict, key=lambda d: d["score"]) + streams = streams[:4] db.close_connection() From ead61bbabd6ceb7dae4f3b4b100716d8f9ebdb63 Mon Sep 17 00:00:00 2001 From: white <122345776@umail.ucc.ie> Date: Thu, 6 Mar 2025 17:17:32 +0000 Subject: [PATCH 4/4] FEAT: Added vods to search bar (needs to be integrated with search bar --- web_server/blueprints/search_bar.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/web_server/blueprints/search_bar.py b/web_server/blueprints/search_bar.py index e853e7c..b4f3631 100644 --- a/web_server/blueprints/search_bar.py +++ b/web_server/blueprints/search_bar.py @@ -56,7 +56,7 @@ def search_results(): users = db.fetchall("SELECT user_id, username, is_live FROM users") for u in users: key = u.get("username") - score = rank_results(query, key) + score = rank_results(query.lower(), key.lower()) u["score"] = score if score < 2: res_dict.append(u) @@ -74,15 +74,29 @@ def search_results(): for s in streams: key = s.get("username") - score = rank_results(query, key) + score = rank_results(query.lower(), key.lower()) s["score"] = score if score < 2: res_dict.append(s) streams = sorted(res_dict, key=lambda d: d["score"]) streams = streams[:4] + # 3 VODs + res_dict = [] + vods = db.fetchall("""SELECT v.vod_id, v.title, u.user_id, u.username + FROM vods as v JOIN users as u + ON v.user_id = u.user_id""") + for v in vods: + key = v.get("title") + score = rank_results(query.lower(), key.lower()) + v["score"] = score + if score < 2: + res_dict.append(v) + vods = sorted(res_dict, key=lambda d: d["score"]) + vods = vods[:4] + db.close_connection() - print(query, streams, users, categories, flush=True) + print(query, streams, users, categories, vods, flush=True) - return jsonify({"streams": streams, "categories": categories, "users": users}) \ No newline at end of file + return jsonify({"streams": streams, "categories": categories, "users": users, "vods": vods}) \ No newline at end of file