From f65fc9ea03d0972ef91e5fdcc3aae070d363e186 Mon Sep 17 00:00:00 2001 From: Tim Kelly <63365669+timotheekelly@users.noreply.github.com> Date: Fri, 10 May 2024 16:23:50 +0100 Subject: [PATCH 01/17] adding session 2 --- .classpath | 40 +++++ .project | 23 +++ .settings/org.eclipse.core.resources.prefs | 4 + .settings/org.eclipse.jdt.core.prefs | 8 + .settings/org.eclipse.m2e.core.prefs | 4 + .../com/mongodb/quickstart/Application.java | 29 +++ .../dtos/AverageItemPricePerStoreDTO.java | 8 + .../dtos/CustomerSatisfactionDTO.java | 8 + .../dtos/DistinctCustomersCountDTO.java | 8 + .../quickstart/dtos/RevenueByLocationDTO.java | 8 + .../quickstart/dtos/SalesByDayOfWeekDTO.java | 8 + .../quickstart/dtos/SalesPerformanceDTO.java | 9 + .../dtos/TotalSalesByLocationDTO.java | 8 + .../mongodb/quickstart/models/Customer.java | 50 ++++++ .../com/mongodb/quickstart/models/Item.java | 53 ++++++ .../com/mongodb/quickstart/models/Sale.java | 95 ++++++++++ .../repositories/SalesCustomRepository.java | 21 +++ .../SalesCustomRepositoryImpl.java | 170 ++++++++++++++++++ .../repositories/SalesRepository.java | 9 + .../AverageCustomerSatisfactionService.java | 21 +++ .../AverageItemPricePerStoreService.java | 21 +++ .../CountDistinctCustomersService.java | 21 +++ .../services/RevenueByLocationService.java | 21 +++ .../services/SalesPerformanceService.java | 21 +++ .../TotalSalesByDayOfWeekService.java | 21 +++ .../services/TotalSalesByLocationService.java | 20 +++ 26 files changed, 709 insertions(+) create mode 100644 .classpath create mode 100644 .project create mode 100644 .settings/org.eclipse.core.resources.prefs create mode 100644 .settings/org.eclipse.jdt.core.prefs create mode 100644 .settings/org.eclipse.m2e.core.prefs create mode 100644 src/main/java/com/mongodb/quickstart/dtos/AverageItemPricePerStoreDTO.java create mode 100644 src/main/java/com/mongodb/quickstart/dtos/CustomerSatisfactionDTO.java create mode 100644 src/main/java/com/mongodb/quickstart/dtos/DistinctCustomersCountDTO.java create mode 100644 src/main/java/com/mongodb/quickstart/dtos/RevenueByLocationDTO.java create mode 100644 src/main/java/com/mongodb/quickstart/dtos/SalesByDayOfWeekDTO.java create mode 100644 src/main/java/com/mongodb/quickstart/dtos/SalesPerformanceDTO.java create mode 100644 src/main/java/com/mongodb/quickstart/dtos/TotalSalesByLocationDTO.java create mode 100644 src/main/java/com/mongodb/quickstart/models/Customer.java create mode 100644 src/main/java/com/mongodb/quickstart/models/Item.java create mode 100644 src/main/java/com/mongodb/quickstart/models/Sale.java create mode 100644 src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepository.java create mode 100644 src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java create mode 100644 src/main/java/com/mongodb/quickstart/repositories/SalesRepository.java create mode 100644 src/main/java/com/mongodb/quickstart/services/AverageCustomerSatisfactionService.java create mode 100644 src/main/java/com/mongodb/quickstart/services/AverageItemPricePerStoreService.java create mode 100644 src/main/java/com/mongodb/quickstart/services/CountDistinctCustomersService.java create mode 100644 src/main/java/com/mongodb/quickstart/services/RevenueByLocationService.java create mode 100644 src/main/java/com/mongodb/quickstart/services/SalesPerformanceService.java create mode 100644 src/main/java/com/mongodb/quickstart/services/TotalSalesByDayOfWeekService.java create mode 100644 src/main/java/com/mongodb/quickstart/services/TotalSalesByLocationService.java diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..fe27910 --- /dev/null +++ b/.classpath @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..b541f46 --- /dev/null +++ b/.project @@ -0,0 +1,23 @@ + + + mdb-java-workshop + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..abdea9a --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..8b94239 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=21 +org.eclipse.jdt.core.compiler.compliance=21 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=21 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/src/main/java/com/mongodb/quickstart/Application.java b/src/main/java/com/mongodb/quickstart/Application.java index a0f32c1..fcec94e 100644 --- a/src/main/java/com/mongodb/quickstart/Application.java +++ b/src/main/java/com/mongodb/quickstart/Application.java @@ -7,6 +7,14 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.ComponentScan; +import com.mongodb.quickstart.services.AverageCustomerSatisfactionService; +import com.mongodb.quickstart.services.AverageItemPricePerStoreService; +import com.mongodb.quickstart.services.CountDistinctCustomersService; +import com.mongodb.quickstart.services.RevenueByLocationService; +import com.mongodb.quickstart.services.SalesPerformanceService; +import com.mongodb.quickstart.services.TotalSalesByDayOfWeekService; +import com.mongodb.quickstart.services.TotalSalesByLocationService; + @SpringBootApplication @ComponentScan(basePackages = "com.mongodb.quickstart") public class Application implements CommandLineRunner { @@ -37,6 +45,27 @@ public void run(String... args) { case "update": context.getBean(Update.class).run(); break; + case "total-sales-by-location": + context.getBean(TotalSalesByLocationService.class).run(); + break; + case "average-customer-satisfaction": + context.getBean(AverageCustomerSatisfactionService.class).run(); + break; + case "average-item-price-per-store": + context.getBean(AverageItemPricePerStoreService.class).run(); + break; + case "count-distinct-customers": + context.getBean(CountDistinctCustomersService.class).run(); + break; + case "total-sales-by-day-of-week": + context.getBean(TotalSalesByDayOfWeekService.class).run(); + break; + case "sales-performance": + context.getBean(SalesPerformanceService.class).run(); + break; + case "revenue-by-location": + context.getBean(RevenueByLocationService.class).run(); + break; case "read": default: context.getBean(Read.class).run(); diff --git a/src/main/java/com/mongodb/quickstart/dtos/AverageItemPricePerStoreDTO.java b/src/main/java/com/mongodb/quickstart/dtos/AverageItemPricePerStoreDTO.java new file mode 100644 index 0000000..a0d8e83 --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/dtos/AverageItemPricePerStoreDTO.java @@ -0,0 +1,8 @@ +package com.mongodb.quickstart.dtos; + +public record AverageItemPricePerStoreDTO(String _id, double averagePrice) { + public AverageItemPricePerStoreDTO(String _id, double averagePrice) { + this._id = _id; + this.averagePrice = averagePrice; + } +} diff --git a/src/main/java/com/mongodb/quickstart/dtos/CustomerSatisfactionDTO.java b/src/main/java/com/mongodb/quickstart/dtos/CustomerSatisfactionDTO.java new file mode 100644 index 0000000..9c53b46 --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/dtos/CustomerSatisfactionDTO.java @@ -0,0 +1,8 @@ +package com.mongodb.quickstart.dtos; + +public record CustomerSatisfactionDTO(String storeLocation, double averageSatisfaction) { + public CustomerSatisfactionDTO(String storeLocation, double averageSatisfaction) { + this.storeLocation = storeLocation; + this.averageSatisfaction = averageSatisfaction; + } +} diff --git a/src/main/java/com/mongodb/quickstart/dtos/DistinctCustomersCountDTO.java b/src/main/java/com/mongodb/quickstart/dtos/DistinctCustomersCountDTO.java new file mode 100644 index 0000000..4bcf749 --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/dtos/DistinctCustomersCountDTO.java @@ -0,0 +1,8 @@ +package com.mongodb.quickstart.dtos; + +public record DistinctCustomersCountDTO(String _id, int count) { + public DistinctCustomersCountDTO(String _id, int count) { + this._id = _id; + this.count = count; + } +} diff --git a/src/main/java/com/mongodb/quickstart/dtos/RevenueByLocationDTO.java b/src/main/java/com/mongodb/quickstart/dtos/RevenueByLocationDTO.java new file mode 100644 index 0000000..faada07 --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/dtos/RevenueByLocationDTO.java @@ -0,0 +1,8 @@ +package com.mongodb.quickstart.dtos; + +public record RevenueByLocationDTO(String storeLocation, double totalRevenue) { + public RevenueByLocationDTO(String storeLocation, double totalRevenue) { + this.storeLocation = storeLocation; + this.totalRevenue = totalRevenue; + } +} diff --git a/src/main/java/com/mongodb/quickstart/dtos/SalesByDayOfWeekDTO.java b/src/main/java/com/mongodb/quickstart/dtos/SalesByDayOfWeekDTO.java new file mode 100644 index 0000000..703ebc5 --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/dtos/SalesByDayOfWeekDTO.java @@ -0,0 +1,8 @@ +package com.mongodb.quickstart.dtos; + +public record SalesByDayOfWeekDTO(String _id, int totalSales) { + public SalesByDayOfWeekDTO(String _id, int totalSales) { + this._id = _id; + this.totalSales = totalSales; + } +} diff --git a/src/main/java/com/mongodb/quickstart/dtos/SalesPerformanceDTO.java b/src/main/java/com/mongodb/quickstart/dtos/SalesPerformanceDTO.java new file mode 100644 index 0000000..25852e3 --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/dtos/SalesPerformanceDTO.java @@ -0,0 +1,9 @@ +package com.mongodb.quickstart.dtos; + +public record SalesPerformanceDTO(String storeLocation, int salesWithCoupons, int salesWithoutCoupons) { + public SalesPerformanceDTO(String storeLocation, int salesWithCoupons, int salesWithoutCoupons) { + this.storeLocation = storeLocation; + this.salesWithCoupons = salesWithCoupons; + this.salesWithoutCoupons = salesWithoutCoupons; + } +} diff --git a/src/main/java/com/mongodb/quickstart/dtos/TotalSalesByLocationDTO.java b/src/main/java/com/mongodb/quickstart/dtos/TotalSalesByLocationDTO.java new file mode 100644 index 0000000..ff875bb --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/dtos/TotalSalesByLocationDTO.java @@ -0,0 +1,8 @@ +package com.mongodb.quickstart.dtos; + +public record TotalSalesByLocationDTO(String _id, int totalSales) { + public TotalSalesByLocationDTO(String _id, int totalSales) { + this._id = _id; + this.totalSales = totalSales; + } +} diff --git a/src/main/java/com/mongodb/quickstart/models/Customer.java b/src/main/java/com/mongodb/quickstart/models/Customer.java new file mode 100644 index 0000000..232d8a4 --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/models/Customer.java @@ -0,0 +1,50 @@ +package com.mongodb.quickstart.models; + +public class Customer { + private String gender; + private int age; + private String email; + private int satisfaction; + + public Customer() { + } + + public Customer(String gender, int age, String email, int satisfaction) { + this.gender = gender; + this.age = age; + this.email = email; + this.satisfaction = satisfaction; + } + + public String getGender() { + return gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public int getSatisfaction() { + return satisfaction; + } + + public void setSatisfaction(int satisfaction) { + this.satisfaction = satisfaction; + } +} \ No newline at end of file diff --git a/src/main/java/com/mongodb/quickstart/models/Item.java b/src/main/java/com/mongodb/quickstart/models/Item.java new file mode 100644 index 0000000..adfa1cf --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/models/Item.java @@ -0,0 +1,53 @@ +package com.mongodb.quickstart.models; + +import java.math.BigDecimal; +import java.util.List; + +public class Item { + private String name; + private List tags; + private BigDecimal price; + private int quantity; + + public Item() { + } + + public Item(String name, List tags, BigDecimal price, int quantity) { + this.name = name; + this.tags = tags; + this.price = price; + this.quantity = quantity; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + + public BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } +} \ No newline at end of file diff --git a/src/main/java/com/mongodb/quickstart/models/Sale.java b/src/main/java/com/mongodb/quickstart/models/Sale.java new file mode 100644 index 0000000..7549f56 --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/models/Sale.java @@ -0,0 +1,95 @@ +package com.mongodb.quickstart.models; + +import java.util.Date; +import java.util.List; + +import org.bson.types.ObjectId; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document("sale") +public class Sale { + + @Id + private ObjectId id; + private Date saleDate = new Date(); + private List items; + private String storeLocation; + private Customer customer; + private boolean couponUsed; + private String purchaseMethod; + + public Sale() { + } + + public Sale(ObjectId id, Date saleDate, List items, String storeLocation, Customer customer, + boolean couponUsed, String purchaseMethod) { + this.id = id; + this.saleDate = saleDate; + this.items = items; + this.storeLocation = storeLocation; + this.customer = customer; + this.couponUsed = couponUsed; + this.purchaseMethod = purchaseMethod; + } + + public Sale(String id, Date saleDate, String storeLocation, Boolean couponUsed, Customer customer, + List items) { + } + + public ObjectId getId() { + return id; + } + + public void setId(ObjectId id) { + this.id = id; + } + + public Date getSaleDate() { + return saleDate; + } + + public void setSaleDate(Date saleDate) { + this.saleDate = saleDate; + } + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } + + public String getStoreLocation() { + return storeLocation; + } + + public void setStoreLocation(String storeLocation) { + this.storeLocation = storeLocation; + } + + public Customer getCustomer() { + return customer; + } + + public void setCustomer(Customer customer) { + this.customer = customer; + } + + public boolean isCouponUsed() { + return couponUsed; + } + + public void setCouponUsed(boolean couponUsed) { + this.couponUsed = couponUsed; + } + + public String getPurchaseMethod() { + return purchaseMethod; + } + + public void setPurchaseMethod(String purchaseMethod) { + this.purchaseMethod = purchaseMethod; + } +} \ No newline at end of file diff --git a/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepository.java b/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepository.java new file mode 100644 index 0000000..0e5a1ec --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepository.java @@ -0,0 +1,21 @@ +package com.mongodb.quickstart.repositories; + +import java.util.List; + +import com.mongodb.quickstart.dtos.AverageItemPricePerStoreDTO; +import com.mongodb.quickstart.dtos.CustomerSatisfactionDTO; +import com.mongodb.quickstart.dtos.DistinctCustomersCountDTO; +import com.mongodb.quickstart.dtos.RevenueByLocationDTO; +import com.mongodb.quickstart.dtos.SalesByDayOfWeekDTO; +import com.mongodb.quickstart.dtos.SalesPerformanceDTO; +import com.mongodb.quickstart.dtos.TotalSalesByLocationDTO; + +public interface SalesCustomRepository { + List calculateTotalSalesByLocation(); + List averageItemPricePerStore(); + List countDistinctCustomersByLocation(); + List totalSalesByDayOfWeek(); + List compareSalesWithAndWithoutCoupons(); + List calculateTotalRevenueByLocation(); + List averageCustomerSatisfactionByLocation(); +} \ No newline at end of file diff --git a/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java b/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java new file mode 100644 index 0000000..86951cb --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java @@ -0,0 +1,170 @@ +package com.mongodb.quickstart.repositories; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Sort; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.aggregation.Aggregation; +import org.springframework.data.mongodb.core.aggregation.AggregationResults; +import org.springframework.data.mongodb.core.aggregation.ConditionalOperators; +import org.springframework.data.mongodb.core.aggregation.ProjectionOperation; +import org.springframework.data.mongodb.core.aggregation.SortOperation; +import org.springframework.data.mongodb.core.aggregation.UnwindOperation; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.aggregation.GroupOperation; +import org.springframework.data.mongodb.core.aggregation.MatchOperation; +import org.springframework.stereotype.Repository; + +import com.mongodb.quickstart.dtos.AverageItemPricePerStoreDTO; +import com.mongodb.quickstart.dtos.CustomerSatisfactionDTO; +import com.mongodb.quickstart.dtos.DistinctCustomersCountDTO; +import com.mongodb.quickstart.dtos.RevenueByLocationDTO; +import com.mongodb.quickstart.dtos.SalesByDayOfWeekDTO; +import com.mongodb.quickstart.dtos.SalesPerformanceDTO; +import com.mongodb.quickstart.dtos.TotalSalesByLocationDTO; + +import java.util.List; + +@Repository +public class SalesCustomRepositoryImpl implements SalesCustomRepository { + + @Autowired + private MongoTemplate mongoTemplate; + + /** + * Question 1: Total Sales by Location + * + * Calculate the total sales grouped by each location and return a result that + * includes the location's name (or ID) and the total sales amount. + */ + @Override + public List calculateTotalSalesByLocation() { + GroupOperation groupStage = Aggregation.group("storeLocation").count().as("totalSales"); + + Aggregation aggregation = Aggregation.newAggregation(groupStage); + + AggregationResults results = mongoTemplate.aggregate(aggregation, "sales", + TotalSalesByLocationDTO.class); + + return results.getMappedResults(); + } + + /** + * Question 2: Customer Satisfaction by Location + * + * Calculate the average customer satisfaction rating for each store location, + * based on a 'satisfactionRating' field in each sale document. Only accept + * satisfaction ratings thats are greater than 1. + */ + @Override + public List averageCustomerSatisfactionByLocation() { + MatchOperation matchStage = Aggregation.match(new Criteria("satisfactionScore").gte(1)); + GroupOperation groupStage = Aggregation.group("storeLocation").avg("satisfactionScore") + .as("averageSatisfaction"); + + Aggregation aggregation = Aggregation.newAggregation(matchStage, groupStage); + + AggregationResults results = mongoTemplate.aggregate(aggregation, "customerFeedback", + CustomerSatisfactionDTO.class); + + return results.getMappedResults(); + } + + /** + * Question 3: Average Price of Items per Store + * + * Calculate the average price of items sold per store and return a result that + * includes the store's name (or ID) and the average price. + */ + @Override + public List averageItemPricePerStore() { + UnwindOperation unwindStage = Aggregation.unwind("items"); + GroupOperation groupStage = Aggregation.group("storeLocation").avg("items.price").as("averagePrice"); + + Aggregation aggregation = Aggregation.newAggregation(unwindStage, groupStage); + + AggregationResults results = mongoTemplate.aggregate(aggregation, "sales", + AverageItemPricePerStoreDTO.class); + + return results.getMappedResults(); + } + + /** + * Question 4: Number of Distinct Customers + * + * Count the number of distinct customers and return a result that includes the + * identifier for grouping and the count of customers. + */ + @Override + public List countDistinctCustomersByLocation() { + GroupOperation groupStage = Aggregation.group("storeLocation").addToSet("customer").as("uniqueCustomers"); + ProjectionOperation projectStage = Aggregation.project().andExpression("size(uniqueCustomers)").as("count"); + + Aggregation aggregation = Aggregation.newAggregation(groupStage, projectStage); + + AggregationResults results = mongoTemplate.aggregate(aggregation, "sales", + DistinctCustomersCountDTO.class); + + return results.getMappedResults(); + } + + /** + * Question 5: Total Sales by Day + * Calculate the total sales grouped by each day of the week and return a result that includes the day's name (or ID) and the + * total sales amount. + */ + @Override + public List totalSalesByDayOfWeek() { + ProjectionOperation projectStage = Aggregation.project().andExpression("dayOfWeek(saleDate)").as("dayOfWeek"); + GroupOperation groupStage = Aggregation.group("dayOfWeek").count().as("totalSales"); + Aggregation aggregation = Aggregation.newAggregation(projectStage, groupStage); + + AggregationResults results = mongoTemplate.aggregate(aggregation, "sales", + SalesByDayOfWeekDTO.class); + + return results.getMappedResults(); + } + + /** + * Question 6: Sum of Sales Revenue by Location + * + * Calculate the total revenue from sales grouped by each location and return a + * result that includes the location's name (or ID) and the total revenue. Sort these from highest to lowest. + */ + @Override + public List calculateTotalRevenueByLocation() { + UnwindOperation unwindStage = Aggregation.unwind("items"); + GroupOperation groupStage = Aggregation.group("storeLocation").sum("items.price").as("totalRevenue"); + SortOperation sortStage = Aggregation.sort(Sort.by(Sort.Direction.DESC, "totalRevenue")); + + Aggregation aggregation = Aggregation.newAggregation(unwindStage, groupStage, sortStage); + + AggregationResults results = mongoTemplate.aggregate(aggregation, "sales", + RevenueByLocationDTO.class); + + return results.getMappedResults(); + } + + /** + * Question 7: Sales Performance Before and After Applying Coupons + * + * Compare the number of sales transactions with and without coupons at each + * store location and return a detailed breakdown. + */ + @Override + public List compareSalesWithAndWithoutCoupons() { + GroupOperation groupStage = Aggregation.group("storeLocation") + .sum(ConditionalOperators.Cond.newBuilder().when(Criteria.where("couponUsed").is(true)).then(1) + .otherwise(0)) + .as("salesWithCoupons").sum(ConditionalOperators.Cond.newBuilder() + .when(Criteria.where("couponUsed").is(false)).then(1).otherwise(0)) + .as("salesWithoutCoupons"); + + Aggregation aggregation = Aggregation.newAggregation(groupStage); + + AggregationResults results = mongoTemplate.aggregate(aggregation, "sales", + SalesPerformanceDTO.class); + + return results.getMappedResults(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/mongodb/quickstart/repositories/SalesRepository.java b/src/main/java/com/mongodb/quickstart/repositories/SalesRepository.java new file mode 100644 index 0000000..3940503 --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/repositories/SalesRepository.java @@ -0,0 +1,9 @@ +package com.mongodb.quickstart.repositories; + +import org.springframework.data.mongodb.repository.MongoRepository; + +import com.mongodb.quickstart.models.Sale; + + +public interface SalesRepository extends MongoRepository, SalesCustomRepository { +} diff --git a/src/main/java/com/mongodb/quickstart/services/AverageCustomerSatisfactionService.java b/src/main/java/com/mongodb/quickstart/services/AverageCustomerSatisfactionService.java new file mode 100644 index 0000000..97818a8 --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/services/AverageCustomerSatisfactionService.java @@ -0,0 +1,21 @@ +package com.mongodb.quickstart.services; + +import com.mongodb.quickstart.dtos.CustomerSatisfactionDTO; +import com.mongodb.quickstart.repositories.SalesCustomRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component("averageCustomerSatisfaction") +public class AverageCustomerSatisfactionService implements Runnable { + + @Autowired + private SalesCustomRepository salesCustomRepository; + + @Override + public void run() { + List results = salesCustomRepository.averageCustomerSatisfactionByLocation(); + results.forEach(System.out::println); + } +} diff --git a/src/main/java/com/mongodb/quickstart/services/AverageItemPricePerStoreService.java b/src/main/java/com/mongodb/quickstart/services/AverageItemPricePerStoreService.java new file mode 100644 index 0000000..ffc4f45 --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/services/AverageItemPricePerStoreService.java @@ -0,0 +1,21 @@ +package com.mongodb.quickstart.services; + +import com.mongodb.quickstart.dtos.AverageItemPricePerStoreDTO; +import com.mongodb.quickstart.repositories.SalesCustomRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component("averageItemPricePerStore") +public class AverageItemPricePerStoreService implements Runnable { + + @Autowired + private SalesCustomRepository salesCustomRepository; + + @Override + public void run() { + List results = salesCustomRepository.averageItemPricePerStore(); + results.forEach(System.out::println); + } +} diff --git a/src/main/java/com/mongodb/quickstart/services/CountDistinctCustomersService.java b/src/main/java/com/mongodb/quickstart/services/CountDistinctCustomersService.java new file mode 100644 index 0000000..b03ecfc --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/services/CountDistinctCustomersService.java @@ -0,0 +1,21 @@ +package com.mongodb.quickstart.services; + +import com.mongodb.quickstart.dtos.DistinctCustomersCountDTO; +import com.mongodb.quickstart.repositories.SalesCustomRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component("countDistinctCustomers") +public class CountDistinctCustomersService implements Runnable { + + @Autowired + private SalesCustomRepository salesCustomRepository; + + @Override + public void run() { + List results = salesCustomRepository.countDistinctCustomersByLocation(); + results.forEach(System.out::println); + } +} diff --git a/src/main/java/com/mongodb/quickstart/services/RevenueByLocationService.java b/src/main/java/com/mongodb/quickstart/services/RevenueByLocationService.java new file mode 100644 index 0000000..3105949 --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/services/RevenueByLocationService.java @@ -0,0 +1,21 @@ +package com.mongodb.quickstart.services; + +import com.mongodb.quickstart.dtos.RevenueByLocationDTO; +import com.mongodb.quickstart.repositories.SalesCustomRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component("revenueByLocation") +public class RevenueByLocationService implements Runnable { + + @Autowired + private SalesCustomRepository salesCustomRepository; + + @Override + public void run() { + List results = salesCustomRepository.calculateTotalRevenueByLocation(); + results.forEach(System.out::println); + } +} diff --git a/src/main/java/com/mongodb/quickstart/services/SalesPerformanceService.java b/src/main/java/com/mongodb/quickstart/services/SalesPerformanceService.java new file mode 100644 index 0000000..1c1f400 --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/services/SalesPerformanceService.java @@ -0,0 +1,21 @@ +package com.mongodb.quickstart.services; + +import com.mongodb.quickstart.dtos.SalesPerformanceDTO; +import com.mongodb.quickstart.repositories.SalesCustomRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component("salesPerformance") +public class SalesPerformanceService implements Runnable { + + @Autowired + private SalesCustomRepository salesCustomRepository; + + @Override + public void run() { + List results = salesCustomRepository.compareSalesWithAndWithoutCoupons(); + results.forEach(System.out::println); + } +} diff --git a/src/main/java/com/mongodb/quickstart/services/TotalSalesByDayOfWeekService.java b/src/main/java/com/mongodb/quickstart/services/TotalSalesByDayOfWeekService.java new file mode 100644 index 0000000..a0a1a97 --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/services/TotalSalesByDayOfWeekService.java @@ -0,0 +1,21 @@ +package com.mongodb.quickstart.services; + +import com.mongodb.quickstart.dtos.SalesByDayOfWeekDTO; +import com.mongodb.quickstart.repositories.SalesCustomRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component("totalSalesByDayOfWeek") +public class TotalSalesByDayOfWeekService implements Runnable { + + @Autowired + private SalesCustomRepository salesCustomRepository; + + @Override + public void run() { + List results = salesCustomRepository.totalSalesByDayOfWeek(); + results.forEach(System.out::println); + } +} diff --git a/src/main/java/com/mongodb/quickstart/services/TotalSalesByLocationService.java b/src/main/java/com/mongodb/quickstart/services/TotalSalesByLocationService.java new file mode 100644 index 0000000..feef6f0 --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/services/TotalSalesByLocationService.java @@ -0,0 +1,20 @@ +package com.mongodb.quickstart.services; + +import com.mongodb.quickstart.dtos.TotalSalesByLocationDTO; +import com.mongodb.quickstart.repositories.SalesCustomRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component("totalSalesByLocation") +public class TotalSalesByLocationService { + + @Autowired + private SalesCustomRepository salesCustomRepository; + + public void run() { + List results = salesCustomRepository.calculateTotalSalesByLocation(); + results.forEach(result -> System.out.println(result)); + } +} From 1ff252d0668a2a8885630d2a3e9cc0b72617c1fa Mon Sep 17 00:00:00 2001 From: Rita Rodrigues Date: Fri, 10 May 2024 16:25:22 +0100 Subject: [PATCH 02/17] Delete .settings directory --- .settings/org.eclipse.core.resources.prefs | 4 ---- .settings/org.eclipse.jdt.core.prefs | 8 -------- .settings/org.eclipse.m2e.core.prefs | 4 ---- 3 files changed, 16 deletions(-) delete mode 100644 .settings/org.eclipse.core.resources.prefs delete mode 100644 .settings/org.eclipse.jdt.core.prefs delete mode 100644 .settings/org.eclipse.m2e.core.prefs diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index abdea9a..0000000 --- a/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,4 +0,0 @@ -eclipse.preferences.version=1 -encoding//src/main/java=UTF-8 -encoding//src/main/resources=UTF-8 -encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 8b94239..0000000 --- a/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,8 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=21 -org.eclipse.jdt.core.compiler.compliance=21 -org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore -org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=21 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f..0000000 --- a/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 From d31c9ea0e25635bdf3d651a214710312c780d2a2 Mon Sep 17 00:00:00 2001 From: Rita Rodrigues Date: Fri, 10 May 2024 17:26:11 +0100 Subject: [PATCH 03/17] fix duplicated bean issue --- .classpath | 40 ------------------- .project | 23 ----------- pom.xml | 30 +++++++------- .../SalesCustomRepositoryImpl.java | 2 + .../repositories/SalesRepository.java | 3 +- .../AverageCustomerSatisfactionService.java | 2 +- 6 files changed, 21 insertions(+), 79 deletions(-) delete mode 100644 .classpath delete mode 100644 .project diff --git a/.classpath b/.classpath deleted file mode 100644 index fe27910..0000000 --- a/.classpath +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.project b/.project deleted file mode 100644 index b541f46..0000000 --- a/.project +++ /dev/null @@ -1,23 +0,0 @@ - - - mdb-java-workshop - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - - diff --git a/pom.xml b/pom.xml index fdb8200..bdbf0d6 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 3.12.1 5.0.0 1.8.0 - 3.2.0 + 3.2.5 3.1.1 @@ -32,24 +32,22 @@ mongodb-crypt ${mongodb-crypt.version} - - - org.springframework.boot - spring-boot-starter - ${spring-boot.version} - - - org.springframework.boot - spring-boot-starter-logging - - - org.springframework.boot spring-boot-starter-data-mongodb ${spring-boot.version} + + ch.qos.logback + logback-classic + 1.4.14 + + + org.slf4j + slf4j-api + 2.0.13 + @@ -57,6 +55,10 @@ org.springframework.boot spring-boot-maven-plugin + ${spring-boot.version} + + com.mongodb.quickstart.Application + org.apache.maven.plugins @@ -73,7 +75,7 @@ ${exec-maven-plugin.version} false - com.mongodb.quickstart.Application + com.mongodb.quickstart.Application diff --git a/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java b/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java index 86951cb..41c44ce 100644 --- a/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java +++ b/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java @@ -1,6 +1,7 @@ package com.mongodb.quickstart.repositories; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Primary; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; @@ -25,6 +26,7 @@ import java.util.List; @Repository +@Primary public class SalesCustomRepositoryImpl implements SalesCustomRepository { @Autowired diff --git a/src/main/java/com/mongodb/quickstart/repositories/SalesRepository.java b/src/main/java/com/mongodb/quickstart/repositories/SalesRepository.java index 3940503..96a963e 100644 --- a/src/main/java/com/mongodb/quickstart/repositories/SalesRepository.java +++ b/src/main/java/com/mongodb/quickstart/repositories/SalesRepository.java @@ -3,7 +3,8 @@ import org.springframework.data.mongodb.repository.MongoRepository; import com.mongodb.quickstart.models.Sale; +import org.springframework.stereotype.Repository; - +@Repository public interface SalesRepository extends MongoRepository, SalesCustomRepository { } diff --git a/src/main/java/com/mongodb/quickstart/services/AverageCustomerSatisfactionService.java b/src/main/java/com/mongodb/quickstart/services/AverageCustomerSatisfactionService.java index 97818a8..97d976c 100644 --- a/src/main/java/com/mongodb/quickstart/services/AverageCustomerSatisfactionService.java +++ b/src/main/java/com/mongodb/quickstart/services/AverageCustomerSatisfactionService.java @@ -7,7 +7,7 @@ import java.util.List; -@Component("averageCustomerSatisfaction") +@Component public class AverageCustomerSatisfactionService implements Runnable { @Autowired From 22496384872bb2c2c7f136795aae34b39c9b0a2a Mon Sep 17 00:00:00 2001 From: Tim Kelly <63365669+timotheekelly@users.noreply.github.com> Date: Fri, 10 May 2024 17:44:09 +0100 Subject: [PATCH 04/17] Update README.md --- README.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/README.md b/README.md index 2f9477b..c178f94 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ spring.data.mongodb.uri=mongodb+srv://:@>t/?retryWrites mvn clean compile ``` +## Session 1 + - Run the `Create` class: ```sh @@ -59,3 +61,44 @@ mvn spring-boot:run -Dspring-boot.run.arguments=delete mvn spring-boot:run -Dspring-boot.run.arguments=mapping ``` +## Session 2 + +- Run the `TotalSalesByLocationService` class: + +```sh + mvn spring-boot:run -Dspring-boot.run.arguments=total-sales-by-location +``` + +- Run the `AverageCustomerSatisfactionService` class: + +```sh +mvn spring-boot:run -Dspring-boot.run.arguments=average-customer-satisfaction +``` + +- Run the `AverageItemPricePerStoreService` class: +```sh +mvn spring-boot:run -Dspring-boot.run.arguments=average-item-price-per-store +``` + +- Run the `CountDistinctCustomersService` class: + +```sh +mvn spring-boot:run -Dspring-boot.run.arguments=count-distinct-customers +``` + +- Run the `TotalSalesByDayOfWeekService` class: +```sh +mvn spring-boot:run -Dspring-boot.run.arguments=total-sales-by-day-of-week +``` + +- Run the `SalesPerformanceService` class: +```sh +mvn spring-boot:run -Dspring-boot.run.arguments=sales-performance +``` + +- Run the `RevenueByLocationService` class: +```sh +mvn spring-boot:run -Dspring-boot.run.arguments=revenue-by-location +``` + +## Session 3 From d9bb63762c537759ec73bc969dc46c3e3bbd025b Mon Sep 17 00:00:00 2001 From: Tim Kelly <63365669+timotheekelly@users.noreply.github.com> Date: Fri, 10 May 2024 17:51:01 +0100 Subject: [PATCH 05/17] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c178f94..0ebd7f7 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ mvn spring-boot:run -Dspring-boot.run.arguments=mapping ``` ## Session 2 +For this session make sure to switch to the `sample_supplies` database in your `application.properties`. - Run the `TotalSalesByLocationService` class: From 41996dd9eea3350f5afa9879c95f72c2c41e123b Mon Sep 17 00:00:00 2001 From: Tim Kelly <63365669+timotheekelly@users.noreply.github.com> Date: Tue, 14 May 2024 11:56:48 +0100 Subject: [PATCH 06/17] Update .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 93f7381..4a24407 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ .idea/ target/ master_key.txt +.classpath +.project +*.prefs From e052292d9c377859a97d7b0c839c54fb063f81ed Mon Sep 17 00:00:00 2001 From: Tim Kelly <63365669+timotheekelly@users.noreply.github.com> Date: Wed, 15 May 2024 20:15:32 +0100 Subject: [PATCH 07/17] Update SalesCustomRepositoryImpl.java --- .../SalesCustomRepositoryImpl.java | 49 ++++++++++++++----- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java b/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java index 41c44ce..0903d4b 100644 --- a/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java +++ b/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java @@ -54,21 +54,35 @@ public List calculateTotalSalesByLocation() { * Question 2: Customer Satisfaction by Location * * Calculate the average customer satisfaction rating for each store location, - * based on a 'satisfactionRating' field in each sale document. Only accept - * satisfaction ratings thats are greater than 1. + * based on a 'customer.satisfaction' field in each sale document. Only accept + * satisfaction ratings thats are greater than or equal to 1. */ @Override public List averageCustomerSatisfactionByLocation() { - MatchOperation matchStage = Aggregation.match(new Criteria("satisfactionScore").gte(1)); - GroupOperation groupStage = Aggregation.group("storeLocation").avg("satisfactionScore") - .as("averageSatisfaction"); + // Match documents where customer satisfaction is greater than or equal to 1 + MatchOperation matchStage = Aggregation.match(Criteria.where("customer.satisfaction").gte(1)); - Aggregation aggregation = Aggregation.newAggregation(matchStage, groupStage); + // Group by store location and calculate average satisfaction + GroupOperation groupStage = Aggregation.group("storeLocation") + .avg("customer.satisfaction").as("averageSatisfaction"); - AggregationResults results = mongoTemplate.aggregate(aggregation, "customerFeedback", - CustomerSatisfactionDTO.class); + // Project the results to match the structure of CustomerSatisfactionDTO + ProjectionOperation projectStage = Aggregation.project() + .andExpression("_id").as("storeLocation") + .andExpression("averageSatisfaction").as("averageSatisfaction"); - return results.getMappedResults(); + // Define the aggregation pipeline with match, group, and project stages + Aggregation aggregation = Aggregation.newAggregation(matchStage, groupStage, projectStage); + + // Execute the aggregation and retrieve the results + AggregationResults results = mongoTemplate.aggregate(aggregation, "sales", + CustomerSatisfactionDTO.class); + + // Optionally print each result (for debugging purposes or logging) + results.getMappedResults().forEach(result -> System.out.println(result)); + + // Return the results as a list of DTOs + return results.getMappedResults(); } /** @@ -155,13 +169,22 @@ public List calculateTotalRevenueByLocation() { @Override public List compareSalesWithAndWithoutCoupons() { GroupOperation groupStage = Aggregation.group("storeLocation") - .sum(ConditionalOperators.Cond.newBuilder().when(Criteria.where("couponUsed").is(true)).then(1) + .sum(ConditionalOperators.Cond.newBuilder() + .when(Criteria.where("couponUsed").is(true)) + .then(1) .otherwise(0)) - .as("salesWithCoupons").sum(ConditionalOperators.Cond.newBuilder() - .when(Criteria.where("couponUsed").is(false)).then(1).otherwise(0)) + .as("salesWithCoupons") + .sum(ConditionalOperators.Cond.newBuilder() + .when(Criteria.where("couponUsed").is(false)) + .then(1).otherwise(0)) .as("salesWithoutCoupons"); + + ProjectionOperation projectStage = Aggregation.project() + .andExpression("_id").as("storeLocation") + .andExpression("salesWithCoupons").as("salesWithCoupons") + .andExpression("salesWithoutCoupons").as("salesWithoutCoupons"); - Aggregation aggregation = Aggregation.newAggregation(groupStage); + Aggregation aggregation = Aggregation.newAggregation(groupStage, projectStage); AggregationResults results = mongoTemplate.aggregate(aggregation, "sales", SalesPerformanceDTO.class); From 4a0af941cd79c575e41da7e443c72e66afdf4b86 Mon Sep 17 00:00:00 2001 From: Tim Kelly <63365669+timotheekelly@users.noreply.github.com> Date: Thu, 16 May 2024 09:51:13 +0100 Subject: [PATCH 08/17] Update README.md --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0ebd7f7..6ace467 100644 --- a/README.md +++ b/README.md @@ -92,14 +92,12 @@ mvn spring-boot:run -Dspring-boot.run.arguments=count-distinct-customers mvn spring-boot:run -Dspring-boot.run.arguments=total-sales-by-day-of-week ``` -- Run the `SalesPerformanceService` class: -```sh -mvn spring-boot:run -Dspring-boot.run.arguments=sales-performance -``` - - Run the `RevenueByLocationService` class: ```sh mvn spring-boot:run -Dspring-boot.run.arguments=revenue-by-location ``` -## Session 3 +- Run the `SalesPerformanceService` class: +```sh +mvn spring-boot:run -Dspring-boot.run.arguments=sales-performance +``` From 34a8c3929cceac940a4f375dcfddfa9d6b4a7bc5 Mon Sep 17 00:00:00 2001 From: Tim Kelly <63365669+timotheekelly@users.noreply.github.com> Date: Thu, 16 May 2024 09:58:04 +0100 Subject: [PATCH 09/17] Update application.properties --- src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 9578319..bf58aea 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,3 +1,3 @@ # src/main/resources/application.properties spring.data.mongodb.uri=mongodb+srv://:@>t/?retryWrites=true&w=majority -spring.data.mongodb.database=sample_training +spring.data.mongodb.database=sample_sales From 9806496f1fd9fd876b88b1ff79e2cfdeb7a53d2f Mon Sep 17 00:00:00 2001 From: Tim Kelly <63365669+timotheekelly@users.noreply.github.com> Date: Thu, 16 May 2024 09:59:10 +0100 Subject: [PATCH 10/17] Update application.properties --- src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index bf58aea..766484f 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,3 +1,3 @@ # src/main/resources/application.properties spring.data.mongodb.uri=mongodb+srv://:@>t/?retryWrites=true&w=majority -spring.data.mongodb.database=sample_sales +spring.data.mongodb.database=sample_supplies From e98c392946cce032d735c57444323e76617b31f3 Mon Sep 17 00:00:00 2001 From: Tim Kelly <63365669+timotheekelly@users.noreply.github.com> Date: Thu, 16 May 2024 11:06:40 +0100 Subject: [PATCH 11/17] Update SalesCustomRepositoryImpl.java --- .../SalesCustomRepositoryImpl.java | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java b/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java index 0903d4b..f2f2dfb 100644 --- a/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java +++ b/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java @@ -148,17 +148,26 @@ public List totalSalesByDayOfWeek() { */ @Override public List calculateTotalRevenueByLocation() { - UnwindOperation unwindStage = Aggregation.unwind("items"); - GroupOperation groupStage = Aggregation.group("storeLocation").sum("items.price").as("totalRevenue"); - SortOperation sortStage = Aggregation.sort(Sort.by(Sort.Direction.DESC, "totalRevenue")); - - Aggregation aggregation = Aggregation.newAggregation(unwindStage, groupStage, sortStage); - - AggregationResults results = mongoTemplate.aggregate(aggregation, "sales", - RevenueByLocationDTO.class); - - return results.getMappedResults(); - } + UnwindOperation unwindStage = Aggregation.unwind("items"); + + ProjectionOperation projectStage = Aggregation.project("storeLocation") + .and("items.price").as("price") + .and("items.quantity").as("quantity") + .andExpression("items.price * items.quantity").as("total"); + + GroupOperation groupStage = Aggregation.group("storeLocation") + .sum("total").as("totalRevenue"); + + ProjectionOperation finalProjectStage = Aggregation.project("totalRevenue") + .and("_id").as("storeLocation"); + + SortOperation sortStage = Aggregation.sort(Sort.by(Sort.Direction.DESC, "totalRevenue")); + + Aggregation aggregation = Aggregation.newAggregation(unwindStage, projectStage, groupStage, finalProjectStage, sortStage); + + AggregationResults results = mongoTemplate.aggregate(aggregation, "sales", RevenueByLocationDTO.class); + + return results.getMappedResults(); /** * Question 7: Sales Performance Before and After Applying Coupons @@ -192,4 +201,4 @@ public List compareSalesWithAndWithoutCoupons() { return results.getMappedResults(); } -} \ No newline at end of file +} From 3cccc1da072b3da617450535f1128a1f8a2fc669 Mon Sep 17 00:00:00 2001 From: Tim Kelly <63365669+timotheekelly@users.noreply.github.com> Date: Thu, 16 May 2024 11:07:41 +0100 Subject: [PATCH 12/17] Update SalesCustomRepositoryImpl.java --- .../repositories/SalesCustomRepositoryImpl.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java b/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java index f2f2dfb..1bbdaf1 100644 --- a/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java +++ b/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java @@ -59,29 +59,20 @@ public List calculateTotalSalesByLocation() { */ @Override public List averageCustomerSatisfactionByLocation() { - // Match documents where customer satisfaction is greater than or equal to 1 MatchOperation matchStage = Aggregation.match(Criteria.where("customer.satisfaction").gte(1)); - // Group by store location and calculate average satisfaction GroupOperation groupStage = Aggregation.group("storeLocation") .avg("customer.satisfaction").as("averageSatisfaction"); - // Project the results to match the structure of CustomerSatisfactionDTO ProjectionOperation projectStage = Aggregation.project() .andExpression("_id").as("storeLocation") .andExpression("averageSatisfaction").as("averageSatisfaction"); - // Define the aggregation pipeline with match, group, and project stages Aggregation aggregation = Aggregation.newAggregation(matchStage, groupStage, projectStage); - // Execute the aggregation and retrieve the results AggregationResults results = mongoTemplate.aggregate(aggregation, "sales", CustomerSatisfactionDTO.class); - - // Optionally print each result (for debugging purposes or logging) - results.getMappedResults().forEach(result -> System.out.println(result)); - - // Return the results as a list of DTOs + return results.getMappedResults(); } From dc7a48d98e38bff939917e3f457c81540627aa4a Mon Sep 17 00:00:00 2001 From: Tim Kelly <63365669+timotheekelly@users.noreply.github.com> Date: Thu, 16 May 2024 16:26:46 +0100 Subject: [PATCH 13/17] Update SalesCustomRepositoryImpl.java --- .../quickstart/repositories/SalesCustomRepositoryImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java b/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java index 1bbdaf1..3457298 100644 --- a/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java +++ b/src/main/java/com/mongodb/quickstart/repositories/SalesCustomRepositoryImpl.java @@ -159,6 +159,7 @@ public List calculateTotalRevenueByLocation() { AggregationResults results = mongoTemplate.aggregate(aggregation, "sales", RevenueByLocationDTO.class); return results.getMappedResults(); + } /** * Question 7: Sales Performance Before and After Applying Coupons From a5d41bab1bf2a979f04bea63727ec2387c142404 Mon Sep 17 00:00:00 2001 From: Tim Kelly <63365669+timotheekelly@users.noreply.github.com> Date: Mon, 27 May 2024 10:48:17 +0100 Subject: [PATCH 14/17] Create MongoConfig.java --- .../quickstart/config/MongoConfig.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/main/java/com/mongodb/quickstart/config/MongoConfig.java diff --git a/src/main/java/com/mongodb/quickstart/config/MongoConfig.java b/src/main/java/com/mongodb/quickstart/config/MongoConfig.java new file mode 100644 index 0000000..27cdb60 --- /dev/null +++ b/src/main/java/com/mongodb/quickstart/config/MongoConfig.java @@ -0,0 +1,38 @@ +package com.mongodb.quickstart.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; + +import com.mongodb.ConnectionString; +import com.mongodb.MongoClientSettings; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; + +@Configuration +public class MongoConfig extends AbstractMongoClientConfiguration { + + @Value("${spring.data.mongodb.uri}") + private String mongoUri; + + @Value("${spring.data.mongodb.database}") + private String databaseName; + + @Override + protected String getDatabaseName() { + return databaseName; + } + + @Bean + @Override + public MongoClient mongoClient() { + ConnectionString connectionString = new ConnectionString(mongoUri); + MongoClientSettings mongoClientSettings = MongoClientSettings.builder() + .applyConnectionString(connectionString) + .applicationName("devrel.springio.workshop.java") + .build(); + + return MongoClients.create(mongoClientSettings); + } +} From 7aa0832d61b4d8260beb85a7a063853f487fee85 Mon Sep 17 00:00:00 2001 From: Rita Rodrigues Date: Mon, 27 May 2024 14:00:25 +0100 Subject: [PATCH 15/17] Update application.properties --- src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 766484f..0bc7e64 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,3 +1,3 @@ # src/main/resources/application.properties -spring.data.mongodb.uri=mongodb+srv://:@>t/?retryWrites=true&w=majority +spring.data.mongodb.uri=mongodb+srv://:@/?retryWrites=true&w=majority spring.data.mongodb.database=sample_supplies From c2765a1e67888f45969df620957fbb00ee0ed8ec Mon Sep 17 00:00:00 2001 From: Rita Rodrigues Date: Mon, 27 May 2024 14:02:01 +0100 Subject: [PATCH 16/17] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6ace467..2910692 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ To get started with MongoDB Atlas and get a free cluster read [this blog post](h Add MongoDB Atlas Cluster URI in # src/main/resources/application.properties: ``` -spring.data.mongodb.uri=mongodb+srv://:@>t/?retryWrites=true&w=majority +spring.data.mongodb.uri=mongodb+srv://:@/?retryWrites=true&w=majority ``` # Command lines From 38f210c23aea3405050d718deaf5a0fea19f98eb Mon Sep 17 00:00:00 2001 From: Tim Kelly <63365669+timotheekelly@users.noreply.github.com> Date: Mon, 27 May 2024 16:04:23 +0100 Subject: [PATCH 17/17] Updating findFirst --- src/main/java/com/mongodb/quickstart/Delete.java | 9 ++------- src/main/java/com/mongodb/quickstart/MappingPOJO.java | 4 +--- src/main/java/com/mongodb/quickstart/Read.java | 3 +-- .../java/com/mongodb/quickstart/StudentRepository.java | 4 ++-- src/main/java/com/mongodb/quickstart/Update.java | 4 ++-- 5 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/mongodb/quickstart/Delete.java b/src/main/java/com/mongodb/quickstart/Delete.java index 1bd9d5e..034e797 100644 --- a/src/main/java/com/mongodb/quickstart/Delete.java +++ b/src/main/java/com/mongodb/quickstart/Delete.java @@ -2,8 +2,6 @@ import com.mongodb.quickstart.models.Grade; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.SpringApplication; import org.springframework.stereotype.Component; @@ -15,14 +13,14 @@ public class Delete { public void run() { // Delete one document - Grade grade = repository.findByStudentId(10000d); + Grade grade = repository.findFirstByStudentId(10000d); if (grade != null) { repository.delete(grade); System.out.println("Deleted grade: " + grade); } // Find and delete one document - grade = repository.findByStudentId(10002d); + grade = repository.findFirstByStudentId(10002d); if (grade != null) { repository.delete(grade); System.out.println("Deleted grade: " + grade); @@ -32,8 +30,5 @@ public void run() { repository.deleteAll(repository.findByStudentIdGreaterThanEqual(10000d)); System.out.println("Deleted all grades with student_id >= 10000."); - // Drop entire collection - repository.deleteAll(); - System.out.println("Deleted the entire grades collection."); } } \ No newline at end of file diff --git a/src/main/java/com/mongodb/quickstart/MappingPOJO.java b/src/main/java/com/mongodb/quickstart/MappingPOJO.java index b0cfaaf..8e8d220 100644 --- a/src/main/java/com/mongodb/quickstart/MappingPOJO.java +++ b/src/main/java/com/mongodb/quickstart/MappingPOJO.java @@ -4,8 +4,6 @@ import com.mongodb.quickstart.models.Score; import org.bson.types.ObjectId; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.SpringApplication; import org.springframework.stereotype.Component; import java.util.ArrayList; @@ -29,7 +27,7 @@ public void run() { System.out.println("Grade inserted: " + newGrade); // Find this grade - Grade grade = repository.findByStudentId(10003d); + Grade grade = repository.findFirstByStudentId(10003d); System.out.println("Grade found: " + (grade != null ? grade : "No data found")); // Update this grade by adding an exam grade diff --git a/src/main/java/com/mongodb/quickstart/Read.java b/src/main/java/com/mongodb/quickstart/Read.java index 19084a1..b5e062d 100644 --- a/src/main/java/com/mongodb/quickstart/Read.java +++ b/src/main/java/com/mongodb/quickstart/Read.java @@ -2,7 +2,6 @@ import com.mongodb.quickstart.models.Grade; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; import java.util.List; @@ -16,7 +15,7 @@ public class Read { public void run() { try { // Find a grade by student ID - Grade grade = repository.findByStudentId(10000d); + Grade grade = repository.findFirstByStudentId(10000d); System.out.println("Student 1 (via Repository): " + (grade != null ? grade : "No data found")); // Find all grades with student IDs greater than or equal to 10000 diff --git a/src/main/java/com/mongodb/quickstart/StudentRepository.java b/src/main/java/com/mongodb/quickstart/StudentRepository.java index be631cf..e2133cd 100644 --- a/src/main/java/com/mongodb/quickstart/StudentRepository.java +++ b/src/main/java/com/mongodb/quickstart/StudentRepository.java @@ -8,8 +8,8 @@ @Repository public interface StudentRepository extends MongoRepository { - Grade findByStudentId(Double studentId); + Grade findFirstByStudentId(Double studentId); List findByStudentIdGreaterThanEqual(Double studentId); List findByStudentIdAndClassIdLessThanEqual(Double studentId, Double classId); Grade findByStudentIdAndClassId(Double studentId, Double classId); -} +} \ No newline at end of file diff --git a/src/main/java/com/mongodb/quickstart/Update.java b/src/main/java/com/mongodb/quickstart/Update.java index a2277be..653da47 100644 --- a/src/main/java/com/mongodb/quickstart/Update.java +++ b/src/main/java/com/mongodb/quickstart/Update.java @@ -17,7 +17,7 @@ public class Update { public void run() { // Update one document by adding a comment - Grade grade = repository.findByStudentId(10000d); + Grade grade = repository.findFirstByStudentId(10000d); if (grade != null) { Grade updatedGrade = repository.save(grade); System.out.println("Grade updated: " + updatedGrade); @@ -44,7 +44,7 @@ public void run() { System.out.println("Updated all grades with student_id >= 10001."); // Find and update - grade = repository.findByStudentId(10000d); + grade = repository.findFirstByStudentId(10000d); if (grade != null) { Grade updated = repository.save(grade); System.out.println("Updated grade after finding: " + updated);