Managing Product Reviews in Go with Data Aggregation

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 codebase, and then gradually build up to a more complex solution involving data aggregation. Let's jump in!

Starter Task: Structures and Functions

For our starter task, we'll lay the foundation by implementing basic operations for managing product reviews. The Review struct encapsulates the details of a product review. Here's a breakdown of the fields:

  • text string — The textual content of the review.
  • rating int — The rating score of the review, ranging from 1 to 5.
  • flagged bool — A boolean indicating whether the review is flagged as inappropriate.

The individual reviews are managed via a ReviewManager. These are the functions we'll implement in our ReviewManager for the starter task:

  • addReview(productId string, reviewId string, reviewText string, rating int) bool — Adds a review to the product specified by productId. If a review with reviewId already exists, it updates the existing review. Returns true if the review was added or updated successfully, false otherwise. Newly added reviews have the flagged attribute set to false initially.

  • getReview(productId string, reviewId string) (Review, bool) — Returns the review details (text, rating, and flagged fields) for the review specified by reviewId under the given productId. The second return value indicates if the review was found.

  • deleteReview(productId string, reviewId string) bool — Deletes the review specified by reviewId under the given productId. Returns true if the review was deleted, false otherwise.

Starter Task Implementation

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

package main

import "fmt"

type Review struct {
    text    string
    rating  int
    flagged bool
}

type ReviewManager struct {
    products map[string]map[string]Review
}

func NewReviewManager() *ReviewManager {
    return &ReviewManager{products: make(map[string]map[string]Review)}
}

func (rm *ReviewManager) addReview(productId, reviewId, reviewText string, rating int) bool {
    if rating < 1 || rating > 5 {
        return false // Invalid rating
    }

    if _, exists := rm.products[productId]; !exists {
        rm.products[productId] = make(map[string]Review)
    }
    rm.products[productId][reviewId] = Review{reviewText, rating, false}
    return true
}

func (rm *ReviewManager) getReview(productId, reviewId string) (Review, bool) {
    if productReviews, exists := rm.products[productId]; exists {
        if review, found := productReviews[reviewId]; found {
            return review, true
        }
    }
    return Review{}, false
}

func (rm *ReviewManager) deleteReview(productId, reviewId string) bool {
    if productReviews, exists := rm.products[productId]; exists {
        if _, found := productReviews[reviewId]; found {
            delete(productReviews, reviewId)
            if len(productReviews) == 0 {
                delete(rm.products, productId) // Remove product if no reviews left
            }
            return true
        }
    }
    return false
}

func main() {
    reviewManager := NewReviewManager()

    // Adding some reviews
    reviewManager.addReview("p1", "r1", "Great product!", 5)
    reviewManager.addReview("p1", "r2", "Not bad", 3)

    // Testing getReview method
    if review, found := reviewManager.getReview("p1", "r1"); found {
        fmt.Printf("Review r1 for p1: {text: %s, rating: %d, flagged: %v}\n", review.text, review.rating, review.flagged)
    } else {
        fmt.Println("Review r1 for p1 not found")
    }

    if _, found := reviewManager.getReview("p1", "r3"); found {
        fmt.Println("Review r3 for p1 found")
    } else {
        fmt.Println("Review r3 for p1 not found")
    }

    // Testing deleteReview method
    if reviewManager.deleteReview("p1", "r2") {
        fmt.Println("Review r2 for p1 deleted successfully")
    } else {
        fmt.Println("Failed to delete review r2 for p1")
    }

    if _, found := reviewManager.getReview("p1", "r2"); found {
        fmt.Println("Review r2 for p1 found")
    } else {
        fmt.Println("Review r2 for p1 not found")
    }
}

This code establishes the foundational functions needed for managing product reviews within a ReviewManager. The addReview function allows for adding a new review or updating an existing one, ensuring each review contains valid rating values between 1 and 5. The getReview function retrieves the review details for a specific product, returning a boolean to indicate whether the product or review exists. The deleteReview function handles the removal of specific reviews, and if no other reviews remain for a product, the product itself is removed from the list.

Now, let's extend this with new features.

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal