Lesson 1

Advanced Product Review Aggregation Techniques

Introduction

Hello, and welcome to today's lesson! Today, we are going to dive into the world of managing product reviews and applying data aggregation in practice. We will start with a relatively simple Starter Task to set up our base and then gradually build up to a more complex solution involving data aggregation. Let's jump in!

Starter Task: Methods and Their Definitions

For our starter task, we will lay the foundation by implementing basic operations for managing product reviews. These are the methods we will need to implement:

  • add_review(self, product_id: str, review_id: str, review_text: str, rating: int) -> bool — adds a review to the product specified by product_id. If a review with review_id already exists, it updates the existing review. Returns True if the review was added or updated successfully, False otherwise.

  • get_review(self, product_id: str, review_id: str) -> dict | None — returns the review details (review_text, rating, and flagged fields) for the review specified by review_id under the given product_id. If the review or product does not exist, returns None.

  • delete_review(self, product_id: str, review_id: str) -> bool — deletes the review specified by review_id under the given product_id. Returns True if the review was deleted, False otherwise.

Starter Task Implementation

Let's look at the code that implements these functionalities:

Python
1class ReviewManager: 2 def __init__(self): 3 self.products = {} 4 5 def add_review(self, product_id: str, review_id: str, review_text: str, rating: int) -> bool: 6 if rating < 1 or rating > 5: 7 return False # Invalid rating 8 if product_id not in self.products: 9 self.products[product_id] = {} 10 self.products[product_id][review_id] = {"text": review_text, "rating": rating, "flagged": False} 11 return True 12 13 def get_review(self, product_id: str, review_id: str) -> dict | None: 14 if product_id in self.products and review_id in self.products[product_id]: 15 review = self.products[product_id][review_id] 16 return {"text": review["text"], "rating": review["rating"], "flagged": review["flagged"]} 17 return None 18 19 def delete_review(self, product_id: str, review_id: str) -> bool: 20 if product_id in self.products and review_id in self.products[product_id]: 21 del self.products[product_id][review_id] 22 if not self.products[product_id]: 23 del self.products[product_id] # Remove product if no reviews left 24 return True 25 return False 26 27# Instantiate the ReviewManager 28review_manager = ReviewManager() 29 30# Adding some reviews 31review_manager.add_review("p1", "r1", "Great product!", 5) 32review_manager.add_review("p1", "r2", "Not bad", 3) 33 34# Testing get_review method 35print(review_manager.get_review("p1", "r1")) # Expected: {"text": "Great product!", "rating": 5, "flagged": false} 36print(review_manager.get_review("p1", "r3")) # Expected: None 37 38# Testing delete_review method 39print(review_manager.delete_review("p1", "r2")) # Expected: True 40print(review_manager.get_review("p1", "r2")) # Expected: None

This code establishes the foundational methods needed for managing product reviews within a ReviewManager class. The add_review method allows for adding a new review or updating an existing one, ensuring each review contains valid rating values between 1 and 5. The get_review method retrieves the review details for a specific product, including the review text and rating, returning None if the product or review doesn't exist. The delete_review method facilitates the removal of a specific review, and if no reviews are left for a product, the product itself is removed from the product list. Together, these methods form the basic operations required to manage a collection of product reviews efficiently.

Now, let's extend this with new features.

New Task: Advanced Functions and Data Aggregation

With our basic review management system in place, we will now introduce new methods to handle more complex operations, such as flagging inappropriate reviews and aggregating review data for a specific product.

Here are the new methods we will add:

  • flag_review(self, product_id: str, review_id: str) -> bool — This method flags a specific review as inappropriate for a given product. Returns True if the review was successfully flagged, False otherwise.

  • aggregate_reviews(self, product_id: str) -> dict | None — This method aggregates review data for a given product, providing statistics such as the total number of reviews, the number of flagged reviews, average rating, and review texts excluding flagged ones. If the product does not have any reviews or does not exist, returns None.

Implementation, Step 1: Adding the 'flag_review' Method

First, let's add functionality to flag a review:

Python
1class ReviewManager: 2 # Existing methods remain unchanged... 3 4 def flag_review(self, product_id: str, review_id: str) -> bool: 5 if product_id in self.products and review_id in self.products[product_id]: 6 self.products[product_id][review_id]["flagged"] = True 7 return True 8 return False 9 10# Instantiate the ReviewManager 11review_manager = ReviewManager() 12 13# Adding some reviews 14review_manager.add_review("p1", "r1", "Great product!", 5) 15review_manager.add_review("p1", "r2", "Not bad", 3) 16review_manager.add_review("p1", "r3", "Terrible", 1) 17 18# Flagging a review 19review_manager.flag_review("p1", "r3") 20 21# Testing flag_review method 22print(review_manager.get_review("p1", "r3")) # Expected: {"text": "Terrible", "rating": 1, "flagged": True}

In this step, we are adding the flag_review method to our ReviewManager class. This method enables users to mark a specific review as inappropriate. It checks whether the product and review exist in the dataset, and if they do, it sets the flagged attribute of the review to True. This flagging mechanism is crucial for maintaining the quality and appropriateness of the reviews in the system.

Step 2: Adding the 'aggregate_reviews' Method

Next, we will implement the method to aggregate reviews:

Python
1class ReviewManager: 2 # Existing methods remain unchanged... 3 4 def flag_review(self, product_id: str, review_id: str) -> bool: 5 if product_id in self.products and review_id in self.products[product_id]: 6 self.products[product_id][review_id]["flagged"] = True 7 return True 8 return False 9 10 def aggregate_reviews(self, product_id: str) -> dict | None: 11 if product_id not in self.products or not self.products[product_id]: 12 return None # No reviews or product doesn't exist 13 14 total_reviews = len(self.products[product_id]) 15 flagged_reviews = 0 16 total_rating = 0 17 review_texts = [] 18 19 for review in self.products[product_id].values(): 20 if review["flagged"]: 21 flagged_reviews += 1 22 else: 23 total_rating += review["rating"] 24 review_texts.append(review["text"]) 25 26 if total_reviews == flagged_reviews: # All reviews are flagged 27 average_rating = 0 28 else: 29 average_rating = total_rating / (total_reviews - flagged_reviews) 30 31 return { 32 "total_reviews": total_reviews, 33 "flagged_reviews": flagged_reviews, 34 "average_rating": average_rating, 35 "review_texts": review_texts 36 } 37 38# Instantiate the ReviewManager 39review_manager = ReviewManager() 40 41# Adding some reviews 42review_manager.add_review("p1", "r1", "Great product!", 5) 43review_manager.add_review("p1", "r2", "Not bad", 3) 44review_manager.add_review("p1", "r3", "Terrible", 1) 45 46# Flagging a review 47review_manager.flag_review("p1", "r3") 48 49# Testing the aggregation method 50print(review_manager.aggregate_reviews("p1")) 51# Expected: 52# { 53# "total_reviews": 3, 54# "flagged_reviews": 1, 55# "average_rating": 4.0, 56# "review_texts": ["Great product!", "Not bad"] 57# }

In this step, the aggregate_reviews method is added to the ReviewManager class. This method aggregates review data for a given product by calculating various statistics, such as the total number of reviews, the number of flagged reviews, the average rating excluding flagged reviews, and a list of review texts that are not flagged. The method first ensures the product exists and contains reviews. It then iterates through the reviews to collect the necessary data, considering only non-flagged reviews for the average rating and review texts. If all reviews are flagged, the average rating defaults to zero. This aggregation provides a comprehensive overview of a product’s review status, useful for both users and administrators.

Conclusion

Great job! Today, you have learned how to manage product reviews and apply data aggregation in practice. We started with basic operations for adding, retrieving, and deleting reviews. Then, we extended our functionality to include flagging reviews and aggregating review data. This gradual build-up demonstrates how to enhance features incrementally and handle more complex data aggregation tasks.

Feel free to practice solving similar challenges to strengthen your skills further. Keep coding, and see you in the next lesson!

Enjoy this lesson? Now it's time to practice with Cosmo!

Practice is how you turn knowledge into actual skills.