removing unwanted table product_category
This commit is contained in:
@@ -41,12 +41,7 @@ exports.removeProduct = async (req, res) => {
|
|||||||
await db.execute(`DELETE FROM Image_URL WHERE ProductID = ?`, [productID]);
|
await db.execute(`DELETE FROM Image_URL WHERE ProductID = ?`, [productID]);
|
||||||
await db.execute(`DELETE FROM History WHERE ProductID = ?`, [productID]);
|
await db.execute(`DELETE FROM History WHERE ProductID = ?`, [productID]);
|
||||||
await db.execute(`DELETE FROM Favorites WHERE ProductID = ?`, [productID]);
|
await db.execute(`DELETE FROM Favorites WHERE ProductID = ?`, [productID]);
|
||||||
await db.execute(`DELETE FROM Product_Category WHERE ProductID = ?`, [
|
|
||||||
productID,
|
|
||||||
]);
|
|
||||||
await db.execute(`DELETE FROM Product_Category WHERE ProductID = ?`, [
|
|
||||||
productID,
|
|
||||||
]);
|
|
||||||
await db.execute(`DELETE FROM Transaction WHERE ProductID = ?`, [
|
await db.execute(`DELETE FROM Transaction WHERE ProductID = ?`, [
|
||||||
productID,
|
productID,
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
SET
|
SET
|
||||||
FOREIGN_KEY_CHECKS = 0;
|
FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
TRUNCATE TABLE Product_Category;
|
|
||||||
|
|
||||||
TRUNCATE TABLE Favorites;
|
TRUNCATE TABLE Favorites;
|
||||||
|
|
||||||
TRUNCATE TABLE History;
|
TRUNCATE TABLE History;
|
||||||
@@ -344,62 +342,6 @@ VALUES
|
|||||||
('/Uploads/Bluetooth-Speaker.jpg', 19),
|
('/Uploads/Bluetooth-Speaker.jpg', 19),
|
||||||
('/Uploads/Backpack.jpg', 20);
|
('/Uploads/Backpack.jpg', 20);
|
||||||
|
|
||||||
-- Insert Product-Category relationships (products with multiple categories)
|
|
||||||
INSERT INTO
|
|
||||||
Product_Category (ProductID, CategoryID)
|
|
||||||
VALUES
|
|
||||||
(1, 1),
|
|
||||||
(1, 17),
|
|
||||||
(1, 20), -- Calculus book: Textbooks, School Supplies, Math Resources
|
|
||||||
(2, 2),
|
|
||||||
(2, 11),
|
|
||||||
(2, 25), -- Laptop: Electronics, Computer Accessories, Smartphones & Tablets
|
|
||||||
(3, 3),
|
|
||||||
(3, 18),
|
|
||||||
(3, 24), -- Desk: Furniture, Office Furniture, Dorm Essentials
|
|
||||||
(4, 4),
|
|
||||||
(4, 26), -- Hoodie: Clothing, Winter Clothing
|
|
||||||
(5, 5),
|
|
||||||
(5, 13), -- Basketball: Sports Equipment, Fitness Equipment
|
|
||||||
(6, 6),
|
|
||||||
(6, 23), -- Guitar: Musical Instruments, Audio Equipment
|
|
||||||
(7, 1),
|
|
||||||
(7, 15),
|
|
||||||
(7, 20), -- Physics book: Textbooks, Lab Equipment, Math & Science Resources
|
|
||||||
(8, 8),
|
|
||||||
(8, 24), -- Mini Fridge: Kitchen Appliances, Dorm Essentials
|
|
||||||
(9, 9),
|
|
||||||
(9, 2), -- PS5 Controller: Gaming, Electronics
|
|
||||||
(10, 10),
|
|
||||||
(10, 5),
|
|
||||||
(10, 13), -- Mountain Bike: Bicycles, Sports Equipment, Fitness Equipment
|
|
||||||
(11, 11),
|
|
||||||
(11, 2), -- Mouse: Computer Accessories, Electronics
|
|
||||||
(12, 15),
|
|
||||||
(12, 17), -- Lab Coat: Lab Equipment, School Supplies
|
|
||||||
(13, 12),
|
|
||||||
(13, 17),
|
|
||||||
(13, 20), -- Calculator: Stationery, School Supplies, Math & Science Resources
|
|
||||||
(14, 13),
|
|
||||||
(14, 5), -- Yoga Mat: Fitness Equipment, Sports Equipment
|
|
||||||
(15, 26),
|
|
||||||
(15, 4),
|
|
||||||
(15, 14), -- Winter Jacket: Winter Clothing, Clothing, Winter Sports
|
|
||||||
(16, 1),
|
|
||||||
(16, 17),
|
|
||||||
(16, 19), -- CS Book: Textbooks, School Supplies, Books (Non-textbook)
|
|
||||||
(17, 24),
|
|
||||||
(17, 2), -- Desk Lamp: Dorm Essentials, Electronics
|
|
||||||
(18, 12),
|
|
||||||
(18, 17),
|
|
||||||
(18, 20), -- Scientific Calculator: Stationery, School Supplies, Math & Science
|
|
||||||
(19, 23),
|
|
||||||
(19, 2),
|
|
||||||
(19, 24), -- Bluetooth Speaker: Audio Equipment, Electronics, Dorm Essentials
|
|
||||||
(20, 22),
|
|
||||||
(20, 17),
|
|
||||||
(20, 24);
|
|
||||||
|
|
||||||
-- Insert History records
|
-- Insert History records
|
||||||
INSERT INTO
|
INSERT INTO
|
||||||
History (HistoryID, UserID, ProductID)
|
History (HistoryID, UserID, ProductID)
|
||||||
|
|||||||
@@ -105,15 +105,6 @@ CREATE TABLE Favorites (
|
|||||||
UNIQUE (UserID, ProductID)
|
UNIQUE (UserID, ProductID)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Product-Category Junction Table (Many-to-Many)
|
|
||||||
CREATE TABLE Product_Category (
|
|
||||||
ProductID INT,
|
|
||||||
CategoryID INT,
|
|
||||||
PRIMARY KEY (ProductID, CategoryID),
|
|
||||||
FOREIGN KEY (ProductID) REFERENCES Product (ProductID) ON DELETE CASCADE,
|
|
||||||
FOREIGN KEY (CategoryID) REFERENCES Category (CategoryID) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Login Authentication table
|
-- Login Authentication table
|
||||||
CREATE TABLE AuthVerification (
|
CREATE TABLE AuthVerification (
|
||||||
UserID INT AUTO_INCREMENT PRIMARY KEY,
|
UserID INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
|||||||
Binary file not shown.
@@ -19,7 +19,7 @@ def delete_user_recommendations(user_id):
|
|||||||
cursor = db_con.cursor()
|
cursor = db_con.cursor()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cursor.execute("DELETE FROM Recommendation WHERE UserID = %s", (user_id,))
|
cursor.execute("DELETE FROM Recommendation WHERE UserID = %s", (user_id))
|
||||||
db_con.commit()
|
db_con.commit()
|
||||||
print(f"Deleted existing recommendations for user {user_id}")
|
print(f"Deleted existing recommendations for user {user_id}")
|
||||||
logging.info(f"Deleted existing recommendations for user {user_id}")
|
logging.info(f"Deleted existing recommendations for user {user_id}")
|
||||||
@@ -32,14 +32,12 @@ def delete_user_recommendations(user_id):
|
|||||||
cursor.close()
|
cursor.close()
|
||||||
db_con.close()
|
db_con.close()
|
||||||
|
|
||||||
def get_random_products(count=10, exclude_list=None):
|
def get_random_products(count=0, exclude_list=None):
|
||||||
"""Get random products from the database, excluding any in the exclude_list"""
|
|
||||||
db_con = database()
|
db_con = database()
|
||||||
cursor = db_con.cursor()
|
cursor = db_con.cursor()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if exclude_list and len(exclude_list) > 0:
|
if exclude_list and len(exclude_list) > 0:
|
||||||
# Convert exclude_list to string for SQL IN clause
|
|
||||||
exclude_str = ', '.join(map(str, exclude_list))
|
exclude_str = ', '.join(map(str, exclude_list))
|
||||||
cursor.execute(f"SELECT ProductID FROM Product WHERE ProductID NOT IN ({exclude_str}) ORDER BY RAND() LIMIT {count}")
|
cursor.execute(f"SELECT ProductID FROM Product WHERE ProductID NOT IN ({exclude_str}) ORDER BY RAND() LIMIT {count}")
|
||||||
else:
|
else:
|
||||||
@@ -55,13 +53,11 @@ def get_random_products(count=10, exclude_list=None):
|
|||||||
cursor.close()
|
cursor.close()
|
||||||
db_con.close()
|
db_con.close()
|
||||||
|
|
||||||
def get_popular_products(count=10):
|
def get_popular_products(count=5):
|
||||||
"""Get popular products based on history table frequency"""
|
|
||||||
db_con = database()
|
db_con = database()
|
||||||
cursor = db_con.cursor()
|
cursor = db_con.cursor()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Get products that appear most frequently in history
|
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT ProductID, COUNT(*) as count
|
SELECT ProductID, COUNT(*) as count
|
||||||
FROM History
|
FROM History
|
||||||
@@ -72,7 +68,6 @@ def get_popular_products(count=10):
|
|||||||
|
|
||||||
popular_products = [row[0] for row in cursor.fetchall()]
|
popular_products = [row[0] for row in cursor.fetchall()]
|
||||||
|
|
||||||
# If not enough popular products, supplement with random ones
|
|
||||||
if len(popular_products) < count:
|
if len(popular_products) < count:
|
||||||
random_products = get_random_products(count - len(popular_products), popular_products)
|
random_products = get_random_products(count - len(popular_products), popular_products)
|
||||||
popular_products.extend(random_products)
|
popular_products.extend(random_products)
|
||||||
@@ -81,22 +76,19 @@ def get_popular_products(count=10):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Error getting popular products: {str(e)}")
|
logging.error(f"Error getting popular products: {str(e)}")
|
||||||
return get_random_products(count) # Fallback to random products
|
return get_random_products(count)
|
||||||
finally:
|
finally:
|
||||||
cursor.close()
|
cursor.close()
|
||||||
db_con.close()
|
db_con.close()
|
||||||
|
|
||||||
def has_user_history_or_recommendations(user_id):
|
def has_user_history_or_recommendations(user_id):
|
||||||
"""Check if user exists in History or Recommendation table"""
|
|
||||||
db_con = database()
|
db_con = database()
|
||||||
cursor = db_con.cursor()
|
cursor = db_con.cursor()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Check if user has history
|
|
||||||
cursor.execute("SELECT COUNT(*) FROM History WHERE UserID = %s", (user_id,))
|
cursor.execute("SELECT COUNT(*) FROM History WHERE UserID = %s", (user_id,))
|
||||||
history_count = cursor.fetchone()[0]
|
history_count = cursor.fetchone()[0]
|
||||||
|
|
||||||
# Check if user has recommendations
|
|
||||||
cursor.execute("SELECT COUNT(*) FROM Recommendation WHERE UserID = %s", (user_id,))
|
cursor.execute("SELECT COUNT(*) FROM Recommendation WHERE UserID = %s", (user_id,))
|
||||||
recommendation_count = cursor.fetchone()[0]
|
recommendation_count = cursor.fetchone()[0]
|
||||||
|
|
||||||
@@ -120,13 +112,11 @@ def get_all_products():
|
|||||||
select_clause = "SELECT p.ProductID"
|
select_clause = "SELECT p.ProductID"
|
||||||
for category in categories:
|
for category in categories:
|
||||||
category_id = category[0]
|
category_id = category[0]
|
||||||
select_clause += f", MAX(CASE WHEN pc.CategoryID = {category_id} THEN 1 ELSE 0 END) AS `Cat_{category_id}`"
|
select_clause += f", MAX(CASE WHEN p.CategoryID = {category_id} THEN 1 ELSE 0 END) AS `Cat_{category_id}`"
|
||||||
|
|
||||||
final_query = f"""
|
final_query = f"""
|
||||||
{select_clause}
|
{select_clause}
|
||||||
FROM Product p
|
FROM Product p
|
||||||
LEFT JOIN Product_Category pc ON p.ProductID = pc.ProductID
|
|
||||||
LEFT JOIN Category c ON pc.CategoryID = c.CategoryID
|
|
||||||
GROUP BY p.ProductID;
|
GROUP BY p.ProductID;
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -137,13 +127,13 @@ def get_all_products():
|
|||||||
product_ids = []
|
product_ids = []
|
||||||
for row in results:
|
for row in results:
|
||||||
text_list = list(row)
|
text_list = list(row)
|
||||||
product_id = text_list.pop(0) # Save the product ID before removing it
|
product_id = text_list.pop(0)
|
||||||
final.append(text_list)
|
final.append(text_list)
|
||||||
product_ids.append(product_id)
|
product_ids.append(product_id)
|
||||||
|
|
||||||
cursor.close()
|
cursor.close()
|
||||||
db_con.close()
|
db_con.close()
|
||||||
return final, product_ids # Return both feature vectors and product IDs
|
return final, product_ids
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Error getting all products: {str(e)}")
|
logging.error(f"Error getting all products: {str(e)}")
|
||||||
cursor.close()
|
cursor.close()
|
||||||
@@ -160,15 +150,13 @@ def get_user_history(user_id):
|
|||||||
|
|
||||||
select_clause = "SELECT p.ProductID"
|
select_clause = "SELECT p.ProductID"
|
||||||
for category in categories:
|
for category in categories:
|
||||||
category_id = category[0] # get the uid of the category and then append that to the new column
|
category_id = category[0]
|
||||||
select_clause += f", MAX(CASE WHEN pc.CategoryID = {category_id} THEN 1 ELSE 0 END) AS `Cat_{category_id}`"
|
select_clause += f", MAX(CASE WHEN p.CategoryID = {category_id} THEN 1 ELSE 0 END) AS `Cat_{category_id}`"
|
||||||
|
|
||||||
final_query = f"""
|
final_query = f"""
|
||||||
{select_clause}
|
{select_clause}
|
||||||
FROM Product p
|
FROM Product p
|
||||||
LEFT JOIN Product_Category pc ON p.ProductID = pc.ProductID
|
WHERE p.ProductID IN (SELECT ProductID FROM History WHERE UserID = {user_id})
|
||||||
LEFT JOIN Category c ON pc.CategoryID = c.CategoryID
|
|
||||||
where p.ProductID in (select ProductID from History where UserID = {user_id})
|
|
||||||
GROUP BY p.ProductID;
|
GROUP BY p.ProductID;
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -191,82 +179,63 @@ def get_user_history(user_id):
|
|||||||
|
|
||||||
def get_recommendations(user_id, top_n=5):
|
def get_recommendations(user_id, top_n=5):
|
||||||
try:
|
try:
|
||||||
# Always delete existing recommendations first
|
|
||||||
delete_user_recommendations(user_id)
|
delete_user_recommendations(user_id)
|
||||||
|
|
||||||
# Check if user has history or recommendations
|
|
||||||
if not has_user_history_or_recommendations(user_id):
|
if not has_user_history_or_recommendations(user_id):
|
||||||
# Cold start: return random products
|
|
||||||
random_recs = get_random_products(top_n)
|
random_recs = get_random_products(top_n)
|
||||||
# Store these random recommendations
|
recommendation_upload(user_id, random_recs)
|
||||||
history_upload(user_id, random_recs)
|
|
||||||
|
|
||||||
# Add 5 more unique random products
|
|
||||||
additional_random = get_random_products(5, random_recs)
|
additional_random = get_random_products(5, random_recs)
|
||||||
history_upload(user_id, additional_random)
|
recommendation_upload(user_id, additional_random)
|
||||||
|
|
||||||
return random_recs + additional_random
|
return random_recs + additional_random
|
||||||
|
|
||||||
# Get all products and user history with their category vectors
|
|
||||||
all_product_features, all_product_ids = get_all_products()
|
all_product_features, all_product_ids = get_all_products()
|
||||||
user_history = get_user_history(user_id)
|
user_history = get_user_history(user_id)
|
||||||
|
|
||||||
if not user_history:
|
if not user_history:
|
||||||
# User exists but has no history yet
|
|
||||||
popular_recs = get_popular_products(top_n)
|
popular_recs = get_popular_products(top_n)
|
||||||
history_upload(user_id, popular_recs)
|
recommendation_upload(user_id, popular_recs)
|
||||||
|
|
||||||
# Add 5 more unique random products
|
|
||||||
additional_random = get_random_products(5, popular_recs)
|
additional_random = get_random_products(5, popular_recs)
|
||||||
history_upload(user_id, additional_random)
|
recommendation_upload(user_id, additional_random)
|
||||||
|
|
||||||
return popular_recs + additional_random
|
return popular_recs + additional_random
|
||||||
|
|
||||||
# Calculate similarity between all products and user history
|
user_profile = np.mean(user_history, axis=0)
|
||||||
user_profile = np.mean(user_history, axis=0) # Average user preferences
|
|
||||||
similarities = cosine_similarity([user_profile], all_product_features)
|
similarities = cosine_similarity([user_profile], all_product_features)
|
||||||
print(similarities)
|
|
||||||
|
|
||||||
# Get indices of the top N products sorted by similarity
|
|
||||||
product_indices = similarities[0].argsort()[-top_n:][::-1]
|
product_indices = similarities[0].argsort()[-top_n:][::-1]
|
||||||
|
|
||||||
# Get the actual product IDs using the indices
|
|
||||||
recommended_product_ids = [all_product_ids[i] for i in product_indices]
|
recommended_product_ids = [all_product_ids[i] for i in product_indices]
|
||||||
|
print(recommended_product_ids)
|
||||||
|
|
||||||
# Upload the core recommendations to the database
|
recommendation_upload(user_id, recommended_product_ids)
|
||||||
history_upload(user_id, recommended_product_ids)
|
|
||||||
|
|
||||||
# Add 5 more unique random products that aren't in the recommendations
|
|
||||||
additional_random = get_random_products(5, recommended_product_ids)
|
additional_random = get_random_products(5, recommended_product_ids)
|
||||||
history_upload(user_id, additional_random)
|
recommendation_upload(user_id, additional_random)
|
||||||
|
|
||||||
# Return both the similarity-based recommendations and the random ones
|
|
||||||
return recommended_product_ids + additional_random
|
return recommended_product_ids + additional_random
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Recommendation error for user {user_id}: {str(e)}")
|
logging.error(f"Recommendation error for user {user_id}: {str(e)}")
|
||||||
# Fallback to random products
|
|
||||||
random_products = get_random_products(top_n + 5)
|
random_products = get_random_products(top_n + 5)
|
||||||
return random_products
|
return random_products
|
||||||
|
|
||||||
def history_upload(userID, products):
|
def recommendation_upload(userID, products):
|
||||||
"""Upload product recommendations to the database"""
|
|
||||||
db_con = database()
|
db_con = database()
|
||||||
cursor = db_con.cursor()
|
cursor = db_con.cursor()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for product_id in products:
|
for product_id in products:
|
||||||
# Use parameterized queries to prevent SQL injection
|
|
||||||
cursor.execute("INSERT INTO Recommendation (UserID, RecommendedProductID) VALUES (%s, %s)",
|
cursor.execute("INSERT INTO Recommendation (UserID, RecommendedProductID) VALUES (%s, %s)",
|
||||||
(userID, product_id))
|
(userID, product_id))
|
||||||
|
|
||||||
# Commit the changes
|
|
||||||
db_con.commit()
|
db_con.commit()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Error uploading recommendations: {str(e)}")
|
logging.error(f"Error uploading recommendations: {str(e)}")
|
||||||
db_con.rollback()
|
db_con.rollback()
|
||||||
finally:
|
finally:
|
||||||
# Close the cursor and connection
|
|
||||||
cursor.close()
|
cursor.close()
|
||||||
db_con.close()
|
db_con.close()
|
||||||
|
|||||||
Reference in New Issue
Block a user