This is an automated email from the ASF dual-hosted git repository.

jleroux pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 2f07f48054 Improved: Optimize the 'get average product rating' method 
logic (OFBIZ-12680)
2f07f48054 is described below

commit 2f07f4805478e0552f074f98dc50df7a3aa001cc
Author: Jacques Le Roux <jacques.le.r...@les7arts.com>
AuthorDate: Tue Aug 30 16:53:49 2022 +0200

    Improved: Optimize the 'get average product rating' method logic 
(OFBIZ-12680)
    
    Problem: When calculating the average product rating for any product, the 
'get
    average product rating' method first retrieves the whole list of reviews and
    then iterates all product reviews to determine.
    
    This approach takes time to respond when there are thousands of reviews of a
    single product. It takes significantly longer to display many products 
together
    with their reviews. (e.g. search result page)
    
    Solution: We can use the 'average' function to get the average rather than
    iterating all the product reviews.
    
    Thanks: sourabh jain for the patch, Priya Sharma to help understand
---
 .../entry/catalog/ProductDetail.groovy             |  2 +-
 .../ofbiz/product/product/ProductWorker.java       | 61 +++++++++++++---------
 2 files changed, 36 insertions(+), 27 deletions(-)

diff --git 
a/applications/order/groovyScripts/entry/catalog/ProductDetail.groovy 
b/applications/order/groovyScripts/entry/catalog/ProductDetail.groovy
index 3150980b20..d715be8501 100644
--- a/applications/order/groovyScripts/entry/catalog/ProductDetail.groovy
+++ b/applications/order/groovyScripts/entry/catalog/ProductDetail.groovy
@@ -210,7 +210,7 @@ if (product) {
     if (reviews) {
         ratingReviews = EntityUtil.filterByAnd(reviews, 
[EntityCondition.makeCondition("productRating", EntityOperator.NOT_EQUAL, 
null)])
         if (ratingReviews) {
-            context.averageRating = 
ProductWorker.getAverageProductRating(product, reviews, productStoreId)
+            context.averageRating = 
ProductWorker.getAverageProductRating(product, reviews, productStoreId, 
delegator)
             context.numRatings = ratingReviews.size()
         }
     }
diff --git 
a/applications/product/src/main/java/org/apache/ofbiz/product/product/ProductWorker.java
 
b/applications/product/src/main/java/org/apache/ofbiz/product/product/ProductWorker.java
index fc46b17946..768f390638 100644
--- 
a/applications/product/src/main/java/org/apache/ofbiz/product/product/ProductWorker.java
+++ 
b/applications/product/src/main/java/org/apache/ofbiz/product/product/ProductWorker.java
@@ -43,6 +43,7 @@ import org.apache.ofbiz.entity.GenericEntityException;
 import org.apache.ofbiz.entity.GenericValue;
 import org.apache.ofbiz.entity.condition.EntityCondition;
 import org.apache.ofbiz.entity.condition.EntityOperator;
+import org.apache.ofbiz.entity.model.DynamicViewEntity;
 import org.apache.ofbiz.entity.util.EntityQuery;
 import org.apache.ofbiz.entity.util.EntityTypeUtil;
 import org.apache.ofbiz.entity.util.EntityUtil;
@@ -657,14 +658,14 @@ public final class ProductWorker {
         } catch (GenericEntityException e) {
             Debug.logError(e, MODULE);
         }
-        return ProductWorker.getAverageProductRating(product, productStoreId);
+        return ProductWorker.getAverageProductRating(product, productStoreId, 
delegator);
     }
 
-    public static BigDecimal getAverageProductRating(GenericValue product, 
String productStoreId) {
-        return getAverageProductRating(product, null, productStoreId);
+    public static BigDecimal getAverageProductRating(GenericValue product, 
String productStoreId, Delegator delegator) {
+        return getAverageProductRating(product, null, productStoreId, 
delegator);
     }
 
-    public static BigDecimal getAverageProductRating(GenericValue product, 
List<GenericValue> reviews, String productStoreId) {
+    public static BigDecimal getAverageProductRating(GenericValue product, 
List<GenericValue> reviews, String productStoreId, Delegator delegator) {
         if (product == null) {
             Debug.logWarning("Invalid product entity passed; unable to obtain 
valid product rating", MODULE);
             return BigDecimal.ZERO;
@@ -685,37 +686,45 @@ public final class ProductWorker {
         if ("PRDR_FLAT".equals(entityFieldType)) {
             productRating = productEntityRating;
         } else {
-            // get the product rating from the ProductReview entity; limit by 
product store if ID is passed
-            Map<String, String> reviewByAnd = UtilMisc.toMap("statusId", 
"PRR_APPROVED");
-            if (productStoreId != null) {
-                reviewByAnd.put("productStoreId", productStoreId);
-            }
-
             // lookup the reviews if we didn't pass them in
             if (reviews == null) {
+                Map<String, String> reviewByAnd = UtilMisc.toMap("statusId", 
"PRR_APPROVED");
+                if (productStoreId != null) {
+                    reviewByAnd.put("productStoreId", productStoreId);
+                }
+                if (product != null) {
+                    reviewByAnd.put("productId", (String) 
product.get("productId"));
+                }
                 try {
-                    reviews = product.getRelated("ProductReview", reviewByAnd, 
UtilMisc.toList("-postedDateTime"), true);
+                    DynamicViewEntity avgProductReview = new 
DynamicViewEntity();
+                    avgProductReview.addMemberEntity("PR", "ProductReview");
+                    avgProductReview.addAlias("PR", "productRatingAvg", 
"productRating", null, null, null, "avg");
+                    avgProductReview.addAlias("PR", "productId");
+                    avgProductReview.addAlias("PR", "statusId");
+                    avgProductReview.addAlias("PR", "productStoreId");
+                    GenericValue averageProductReview = 
EntityQuery.use(delegator).select("productRatingAvg")
+                            
.from(avgProductReview).where(reviewByAnd).queryFirst();
+                    productRating = 
averageProductReview.getBigDecimal("productRatingAvg");
                 } catch (GenericEntityException e) {
                     Debug.logError(e, MODULE);
                 }
-            }
-
-            // tally the average
-            BigDecimal ratingTally = BigDecimal.ZERO;
-            BigDecimal numRatings = BigDecimal.ZERO;
-            if (reviews != null) {
-                for (GenericValue productReview: reviews) {
-                    BigDecimal rating = 
productReview.getBigDecimal("productRating");
-                    if (rating != null) {
-                        ratingTally = ratingTally.add(rating);
-                        numRatings = numRatings.add(BigDecimal.ONE);
+            } else {
+                // tally the average
+                BigDecimal ratingTally = BigDecimal.ZERO;
+                BigDecimal numRatings = BigDecimal.ZERO;
+                if (reviews != null) {
+                    for (GenericValue productReview: reviews) {
+                        BigDecimal rating = 
productReview.getBigDecimal("productRating");
+                        if (rating != null) {
+                            ratingTally = ratingTally.add(rating);
+                            numRatings = numRatings.add(BigDecimal.ONE);
+                        }
                     }
                 }
+                if (ratingTally.compareTo(BigDecimal.ZERO) > 0 && 
numRatings.compareTo(BigDecimal.ZERO) > 0) {
+                    productRating = ratingTally.divide(numRatings, 
GEN_ROUNDING);
+                }
             }
-            if (ratingTally.compareTo(BigDecimal.ZERO) > 0 && 
numRatings.compareTo(BigDecimal.ZERO) > 0) {
-                productRating = ratingTally.divide(numRatings, GEN_ROUNDING);
-            }
-
             if ("PRDR_MIN".equals(entityFieldType)) {
                 // check for min
                 if (productEntityRating.compareTo(productRating) > 0) {

Reply via email to