Merge branch 'main' of https://github.com/john-david3/cs3305-team11
This commit is contained in:
@@ -4,6 +4,26 @@ from utils.utils import sanitize
|
|||||||
|
|
||||||
search_bp = Blueprint("search", __name__)
|
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"])
|
@search_bp.route("/search", methods=["POST"])
|
||||||
def search_results():
|
def search_results():
|
||||||
"""
|
"""
|
||||||
@@ -20,119 +40,63 @@ def search_results():
|
|||||||
|
|
||||||
# Get the most accurate search results
|
# Get the most accurate search results
|
||||||
# 3 categories
|
# 3 categories
|
||||||
categories = db.fetchall("""
|
res_dict = []
|
||||||
SELECT bm25(category_fts) AS score, c.category_id, c.category_name
|
categories = db.fetchall("SELECT category_id, category_name FROM categories")
|
||||||
FROM categories AS c
|
for c in categories:
|
||||||
INNER JOIN category_fts AS f ON c.category_id = f.category_id
|
key = c.get("category_name")
|
||||||
WHERE f.category_name LIKE '%' || ? || '%'
|
score = rank_results(query.lower(), key.lower())
|
||||||
ORDER BY score ASC
|
c["score"] = score
|
||||||
LIMIT 4;
|
if score < 2:
|
||||||
""", (query,))
|
res_dict.append(c)
|
||||||
|
categories = sorted(res_dict, key=lambda d: d["score"])
|
||||||
|
categories = categories[:4]
|
||||||
|
|
||||||
# 3 users
|
# 3 users
|
||||||
users = db.fetchall("""
|
res_dict = []
|
||||||
SELECT bm25(user_fts) AS score, u.user_id, u.username, u.is_live
|
users = db.fetchall("SELECT user_id, username, is_live FROM users")
|
||||||
FROM users AS u
|
for u in users:
|
||||||
INNER JOIN user_fts AS f ON u.user_id = f.user_id
|
key = u.get("username")
|
||||||
WHERE f.username LIKE '%' || ? || '%'
|
score = rank_results(query.lower(), key.lower())
|
||||||
ORDER BY score ASC
|
u["score"] = score
|
||||||
LIMIT 4;
|
if score < 2:
|
||||||
""", (query,))
|
res_dict.append(u)
|
||||||
|
users = sorted(res_dict, key=lambda d: d["score"])
|
||||||
|
users = users[:4]
|
||||||
|
|
||||||
# 3 streams
|
# 3 streams
|
||||||
streams = db.fetchall("""
|
res_dict = []
|
||||||
SELECT bm25(stream_fts) AS score, s.user_id, s.title, s.num_viewers, c.category_name, u.username
|
streams = db.fetchall("""SELECT s.user_id, s.title, s.num_viewers, c.category_name, u.username
|
||||||
FROM streams AS s
|
FROM streams AS s
|
||||||
INNER JOIN stream_fts AS f ON s.user_id = f.user_id
|
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 users AS u ON s.user_id = u.user_id
|
||||||
INNER JOIN categories AS c ON s.category_id = c.category_id
|
INNER JOIN categories AS c ON s.category_id = c.category_id
|
||||||
WHERE f.title LIKE '%' || ? || '%'
|
""")
|
||||||
ORDER BY score ASC
|
|
||||||
LIMIT 4;
|
for s in streams:
|
||||||
""", (query,))
|
key = s.get("username")
|
||||||
|
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()
|
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})
|
return jsonify({"streams": streams, "categories": categories, "users": users, "vods": vods})
|
||||||
|
|
||||||
@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})
|
|
||||||
Binary file not shown.
@@ -1,114 +0,0 @@
|
|||||||
/* Full text search queries for categories */
|
|
||||||
DROP TABLE IF EXISTS category_fts;
|
|
||||||
CREATE VIRTUAL TABLE category_fts
|
|
||||||
USING fts5 (category_id, category_name);
|
|
||||||
|
|
||||||
INSERT INTO category_fts (category_id, category_name)
|
|
||||||
SELECT category_id, category_name
|
|
||||||
FROM categories;
|
|
||||||
|
|
||||||
-- Triggers that inserts new titles into category_fts
|
|
||||||
DROP TRIGGER IF EXISTS insert_category_fts;
|
|
||||||
CREATE TRIGGER insert_category_fts
|
|
||||||
AFTER INSERT ON categories
|
|
||||||
BEGIN
|
|
||||||
INSERT INTO category_fts(category_id, category_name)
|
|
||||||
VALUES (NEW.category_id, NEW.category_name);
|
|
||||||
END;
|
|
||||||
|
|
||||||
DROP TRIGGER IF EXISTS update_category_fts;
|
|
||||||
CREATE TRIGGER update_category_fts
|
|
||||||
AFTER UPDATE ON categories
|
|
||||||
BEGIN
|
|
||||||
UPDATE category_fts
|
|
||||||
SET
|
|
||||||
category_id = NEW.category_id,
|
|
||||||
category_name = NEW.category_name
|
|
||||||
WHERE category_id = NEW.category_id;
|
|
||||||
END;
|
|
||||||
|
|
||||||
DROP TRIGGER IF EXISTS delete_category_fts;
|
|
||||||
CREATE TRIGGER delete_category_fts
|
|
||||||
AFTER DELETE ON categories
|
|
||||||
BEGIN
|
|
||||||
DELETE FROM category_fts
|
|
||||||
WHERE category_id = OLD.category_id;
|
|
||||||
END;
|
|
||||||
|
|
||||||
/* Full text search queries for users */
|
|
||||||
DROP TABLE IF EXISTS user_fts;
|
|
||||||
CREATE VIRTUAL TABLE user_fts
|
|
||||||
USING fts5 (user_id, username, is_live);
|
|
||||||
|
|
||||||
INSERT INTO user_fts (user_id, username, is_live)
|
|
||||||
SELECT user_id, username, is_live
|
|
||||||
FROM users;
|
|
||||||
|
|
||||||
-- Triggers that inserts new titles into user_fts
|
|
||||||
DROP TRIGGER IF EXISTS insert_user_fts;
|
|
||||||
CREATE TRIGGER insert_user_fts
|
|
||||||
AFTER INSERT ON users
|
|
||||||
BEGIN
|
|
||||||
INSERT INTO user_fts(user_id, username, is_live)
|
|
||||||
VALUES (NEW.user_id, NEW.username, NEW.is_live);
|
|
||||||
END;
|
|
||||||
|
|
||||||
DROP TRIGGER IF EXISTS update_user_fts;
|
|
||||||
CREATE TRIGGER update_user_fts
|
|
||||||
AFTER UPDATE ON users
|
|
||||||
BEGIN
|
|
||||||
UPDATE user_fts
|
|
||||||
SET
|
|
||||||
user_id = NEW.user_id,
|
|
||||||
username = NEW.username,
|
|
||||||
is_live = NEW.is_live
|
|
||||||
WHERE user_id = NEW.user_id;
|
|
||||||
END;
|
|
||||||
|
|
||||||
DROP TRIGGER IF EXISTS delete_user_fts;
|
|
||||||
CREATE TRIGGER delete_user_fts
|
|
||||||
AFTER DELETE ON users
|
|
||||||
BEGIN
|
|
||||||
DELETE FROM user_fts
|
|
||||||
WHERE user_id = OLD.user_id;
|
|
||||||
END;
|
|
||||||
|
|
||||||
|
|
||||||
/* Full text search queries for users */
|
|
||||||
DROP TABLE IF EXISTS stream_fts;
|
|
||||||
CREATE VIRTUAL TABLE stream_fts
|
|
||||||
USING fts5 (user_id, title, num_viewers, category_id);
|
|
||||||
|
|
||||||
INSERT INTO stream_fts (user_id, title, num_viewers, category_id)
|
|
||||||
SELECT user_id, title, num_viewers, category_id
|
|
||||||
FROM streams;
|
|
||||||
|
|
||||||
-- Triggers that inserts new titles into stream_fts
|
|
||||||
DROP TRIGGER IF EXISTS insert_stream_fts;
|
|
||||||
CREATE TRIGGER insert_stream_fts
|
|
||||||
AFTER INSERT ON streams
|
|
||||||
BEGIN
|
|
||||||
INSERT INTO stream_fts(user_id, title, num_viewers, category_id)
|
|
||||||
VALUES (NEW.user_id, NEW.title, NEW.num_viewers, NEW.category_id);
|
|
||||||
END;
|
|
||||||
|
|
||||||
DROP TRIGGER IF EXISTS update_stream_fts;
|
|
||||||
CREATE TRIGGER update_stream_fts
|
|
||||||
AFTER UPDATE ON streams
|
|
||||||
BEGIN
|
|
||||||
UPDATE stream_fts
|
|
||||||
SET
|
|
||||||
user_id = NEW.user_id,
|
|
||||||
title = NEW.title,
|
|
||||||
num_viewers = NEW.num_viewers,
|
|
||||||
category_id = NEW.category_id
|
|
||||||
WHERE user_id = NEW.user_id;
|
|
||||||
END;
|
|
||||||
|
|
||||||
DROP TRIGGER IF EXISTS delete_stream_fts;
|
|
||||||
CREATE TRIGGER delete_stream_fts
|
|
||||||
AFTER DELETE ON streams
|
|
||||||
BEGIN
|
|
||||||
DELETE FROM stream_fts
|
|
||||||
WHERE user_id = OLD.user_id;
|
|
||||||
END;
|
|
||||||
Reference in New Issue
Block a user