ℹ️ Select 'Choose Exercise', or randomize 'Next Random Exercise' in selected language.

Choose Exercise:
Timer 00:00
WPM --
Score --
Acc --
Correct chars --

GraphQL Field Resolver Data Aggregation

GraphQL

Goal -- WPM

Ready
Exercise Algorithm Area
1package com.example.graphql.resolvers;
2
3import com.example.graphql.models.Product;
4import com.example.graphql.models.Review;
5import com.example.graphql.models.User;
6import com.example.graphql.services.ProductService;
7import com.example.graphql.services.ReviewService;
8import com.example.graphql.services.UserService;
9
10import java.util.List;
11import java.util.ArrayList;
12import java.util.Map;
13import java.util.HashMap;
14
15public class AggregationResolver {
16
17private ProductService productService;
18private ReviewService reviewService;
19private UserService userService;
20
21public AggregationResolver(ProductService prodService, ReviewService revService, UserService userServ) {
22this.productService = prodService;
23this.reviewService = revService;
24this.userService = userServ;
25}
26
27/**
28* Fetches product details and aggregates associated reviews and author information.
29*
30* @param productId The ID of the product to fetch.
31* @return A map containing product details, a list of reviews, and author details.
32*/
33public Map<String, Object> getProductWithAggregatedData(String productId) {
34Map<String, Object> result = new HashMap<>();
35
36// 1. Fetch Product Details
37Product product = productService.getProductById(productId);
38if (product == null) {
39// Handle case where product does not exist
40System.err.println("Error: Product with ID " + productId + " not found.");
41return result; // Return empty map if product is not found
42}
43result.put("product", product);
44
45// 2. Fetch and Aggregate Reviews
46List<Review> reviews = reviewService.getReviewsForProduct(productId);
47List<Map<String, Object>> aggregatedReviews = new ArrayList<>();
48
49if (reviews != null && !reviews.isEmpty()) {
50for (Review review : reviews) {
51Map<String, Object> reviewData = new HashMap<>();
52reviewData.put("id", review.getId());
53reviewData.put("rating", review.getRating());
54reviewData.put("comment", review.getComment());
55
56// Fetch author details for each review
57User author = userService.getUserById(review.getAuthorId());
58if (author != null) {
59Map<String, Object> authorInfo = new HashMap<>();
60authorInfo.put("id", author.getId());
61authorInfo.put("username", author.getUsername());
62reviewData.put("author", authorInfo);
63} else {
64// Handle case where author is not found for a review
65System.err.println("Warning: Author not found for review ID " + review.getId());
66reviewData.put("author", null); // Indicate author not found
67}
68aggregatedReviews.add(reviewData);
69}
70} else {
71// Handle case where no reviews are found for the product
72System.out.println("Info: No reviews found for product ID " + productId);
73}
74result.put("reviews", aggregatedReviews);
75
76// 3. Aggregate related data (e.g., average rating)
77double averageRating = calculateAverageRating(aggregatedReviews);
78result.put("averageRating", averageRating);
79
80return result;
81}
82
83/**
84* Calculates the average rating from a list of aggregated review data.
85*
86* @param aggregatedReviews A list of maps, each representing a review.
87* @return The average rating, or 0.0 if no reviews are provided.
88*/
89private double calculateAverageRating(List<Map<String, Object>> aggregatedReviews) {
90if (aggregatedReviews == null || aggregatedReviews.isEmpty()) {
91return 0.0;
92}
93
94double totalRating = 0;
95int reviewCount = 0;
96
97for (Map<String, Object> reviewData : aggregatedReviews) {
98Object ratingObj = reviewData.get("rating");
99if (ratingObj instanceof Number) {
100totalRating += ((Number) ratingObj).doubleValue();
101reviewCount++;
102}
103}
104
105// Avoid division by zero if no valid ratings were found
106if (reviewCount == 0) {
107return 0.0;
108}
109
110return totalRating / reviewCount;
111}
112
113// Mock services for demonstration purposes
114private static class ProductService {
115public Product getProductById(String id) { return new Product(id, "Sample Product"); }
116}
117private static class ReviewService {
118public List<Review> getReviewsForProduct(String productId) {
119List<Review> reviews = new ArrayList<>();
120if ("prod123".equals(productId)) {
121reviews.add(new Review("rev1", "prod123", "userA", 5, "Great!"));
122reviews.add(new Review("rev2", "prod123", "userB", 4, "Good."));
123}
124return reviews;
125}
126}
127private static class UserService {
128public User getUserById(String id) {
129Map<String, User> users = new HashMap<>();
130users.put("userA", new User("userA", "Alice"));
131users.put("userB", new User("userB", "Bob"));
132return users.get(id);
133}
134}
135
136// Mock models
137private static class Product { String id; String name; Product(String id, String name) { this.id = id; this.name = name; } public String getId() { return id; } public String getName() { return name; } }
138private static class Review { String id; String productId; String authorId; int rating; String comment; Review(String id, String productId, String authorId, int rating, String comment) { this.id = id; this.productId = productId; this.authorId = authorId; this.rating = rating; this.comment = comment; } public String getId() { return id; } public String getProductId() { return productId; } public String getAuthorId() { return authorId; } public int getRating() { return rating; } public String getComment() { return comment; } }
139private static class User { String id; String username; User(String id, String username) { this.id = id; this.username = username; } public String getId() { return id; } public String getUsername() { return username; } }
140}
Algorithm description viewbox

GraphQL Field Resolver Data Aggregation

Algorithm description:

This GraphQL resolver function aggregates data for a specific product. It first fetches the product details, then retrieves all associated reviews, and for each review, it fetches the author's information. Finally, it calculates and includes the average rating of the product. This pattern is common in GraphQL for enriching data from a primary entity with related information from other entities.

Algorithm explanation:

The `getProductWithAggregatedData` function orchestrates data fetching and aggregation for a product. It starts by fetching the `Product` using its ID. If the product is not found, it returns an empty map. Otherwise, it proceeds to fetch all `Review` objects associated with the product. For each review, it fetches the `User` who authored it. This nested fetching pattern is a core aspect of GraphQL resolvers. The time complexity is roughly O(P + R * (U + C)), where P is the time to fetch a product, R is the number of reviews, U is the time to fetch a user, and C is the time to process/aggregate data for a review. The space complexity is O(R * (U_data + R_data)), accounting for storing aggregated review and author data. An invariant is that `aggregatedReviews` will only contain data for reviews where the author could be successfully fetched, or will explicitly mark the author as null if not found.

Pseudocode:

FUNCTION getProductWithAggregatedData(productId):
  SET result = empty map
  FETCH product = productService.getProductById(productId)

  IF product IS null:
    PRINT error
    RETURN result
  ADD product to result map under key "product"

  FETCH reviews = reviewService.getReviewsForProduct(productId)
  SET aggregatedReviews = empty list

  IF reviews IS NOT null AND NOT empty:
    FOR EACH review IN reviews:
      SET reviewData = empty map
      ADD review.id, review.rating, review.comment to reviewData

      FETCH author = userService.getUserById(review.authorId)
      IF author IS NOT null:
        SET authorInfo = empty map
        ADD author.id, author.username to authorInfo
        ADD authorInfo to reviewData under key "author"
      ELSE:
        PRINT warning
        ADD null to reviewData under key "author"
      ADD reviewData to aggregatedReviews
  ELSE:
    PRINT info message
  ADD aggregatedReviews to result map under key "reviews"

  CALCULATE averageRating = calculateAverageRating(aggregatedReviews)
  ADD averageRating to result map under key "averageRating"

  RETURN result

FUNCTION calculateAverageRating(aggregatedReviews):
  IF aggregatedReviews IS null OR empty:
    RETURN 0.0

  SET totalRating = 0
  SET reviewCount = 0

  FOR EACH reviewData IN aggregatedReviews:
    IF reviewData contains "rating" AND it's a number:
      ADD rating to totalRating
      INCREMENT reviewCount

  IF reviewCount IS 0:
    RETURN 0.0
  ELSE:
    RETURN totalRating / reviewCount