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);