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

sergehuber pushed a commit to branch UNOMI-1014-followup-tests-javadoc
in repository https://gitbox.apache.org/repos/asf/unomi.git

commit a62a4f293aff47ebff73c62a4578976b7e59f375
Author: Serge Huber <[email protected]>
AuthorDate: Fri Oct 23 13:22:48 2026 +0200

    UNOMI-1014: Test aggregates and metrics without a condition; fix _all docs
    
    Cover the non-optimized aggregate and the metrics query without a
    condition in the tenant-scoping IT. Javadoc no longer describes _all as
    a global count: it is the current tenant's item count, and a null
    AggregateQuery takes the optimized path that does not return it.
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 .../org/apache/unomi/api/services/QueryService.java |  4 ++--
 .../apache/unomi/itests/PersistenceServiceIT.java   | 21 +++++++++++++++++++++
 .../unomi/persistence/spi/PersistenceService.java   |  4 ++--
 .../unomi/rest/endpoints/QueryServiceEndPoint.java  |  2 +-
 4 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/api/src/main/java/org/apache/unomi/api/services/QueryService.java 
b/api/src/main/java/org/apache/unomi/api/services/QueryService.java
index b4b657825..e181a34b5 100644
--- a/api/src/main/java/org/apache/unomi/api/services/QueryService.java
+++ b/api/src/main/java/org/apache/unomi/api/services/QueryService.java
@@ -41,7 +41,7 @@ public interface QueryService {
 
     /**
      * Counts items of the given type grouped by property values, optionally 
filtered by an aggregate query.
-     * Also returns the global document count when {@code query} is {@code 
null}.
+     * When {@code query} is not {@code null}, also returns {@code _all}, the 
number of items of that type in the current tenant.
      *
      * @param itemType item type name from the item class {@code ITEM_TYPE} 
field
      * @param property property to aggregate on
@@ -55,7 +55,7 @@ public interface QueryService {
 
     /**
      * Counts items of the given type grouped by property values using an 
optimized aggregate query.
-     * Does not return a global document count.
+     * Does not return the {@code _all} item count.
      *
      * @param itemType item type name from the item class {@code ITEM_TYPE} 
field
      * @param property property to aggregate on
diff --git 
a/itests/src/test/java/org/apache/unomi/itests/PersistenceServiceIT.java 
b/itests/src/test/java/org/apache/unomi/itests/PersistenceServiceIT.java
index fdbd2b296..66f7a6420 100644
--- a/itests/src/test/java/org/apache/unomi/itests/PersistenceServiceIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/PersistenceServiceIT.java
@@ -309,6 +309,27 @@ public class PersistenceServiceIT extends BaseIT {
                     DEFAULT_TRYING_TIMEOUT, DEFAULT_TRYING_TRIES);
             Assert.assertEquals(7.0, metrics.get("_sum"), 0.001);
             Assert.assertEquals(1.0, metrics.get("_count"), 0.001);
+
+            // Non-optimized path without a condition: this is where the 
global aggregation used to count every tenant.
+            Map<String, Long> termsNonOptimizedNoCondition = keepTrying(
+                    "Non-optimized terms aggregate without a condition should 
only count the current tenant",
+                    () -> persistenceService.aggregateQuery(null, byFirstName, 
Profile.ITEM_TYPE),
+                    r -> r != null && Long.valueOf(1L).equals(r.get("Alice")) 
&& !r.containsKey("Bob"),
+                    DEFAULT_TRYING_TIMEOUT, DEFAULT_TRYING_TRIES);
+            Assert.assertEquals(Long.valueOf(1L), 
termsNonOptimizedNoCondition.get("Alice"));
+            Assert.assertNull(termsNonOptimizedNoCondition.get("Bob"));
+            Assert.assertEquals("_all must be the current tenant's count",
+                    termsWithCondition.get("_all"), 
termsNonOptimizedNoCondition.get("_all"));
+            Assert.assertNull("No condition means no _filtered", 
termsNonOptimizedNoCondition.get("_filtered"));
+
+            Map<String, Double> metricsNoCondition = keepTrying(
+                    "Metrics without a condition should only include the 
current tenant",
+                    () -> persistenceService.getSingleValuesMetrics(null, new 
String[]{"sum", "count"},
+                            AGE_PROPERTY, Profile.ITEM_TYPE),
+                    r -> r != null && r.get("_sum") != null && r.get("_sum") 
== 7.0,
+                    DEFAULT_TRYING_TIMEOUT, DEFAULT_TRYING_TRIES);
+            Assert.assertEquals(7.0, metricsNoCondition.get("_sum"), 0.001);
+            Assert.assertEquals(1.0, metricsNoCondition.get("_count"), 0.001);
         } finally {
             try {
                 
executionContextManager.executeAsTenant(otherTenant.getItemId(), () -> {
diff --git 
a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/PersistenceService.java
 
b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/PersistenceService.java
index 2c64c1b01..430e71ac8 100644
--- 
a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/PersistenceService.java
+++ 
b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/PersistenceService.java
@@ -663,7 +663,7 @@ public interface PersistenceService {
     /**
      * Aggregates item counts for the given type, optionally filtered by 
condition and
      * aggregated according to the specified {@link BaseAggregate}.
-     * Also return the global count of document matching the {@code ITEM_TYPE}
+     * Also returns {@code _all}, the number of items of the {@code ITEM_TYPE} 
in the current tenant.
      *
      * @param filter    the condition the items must match or {@code null} if 
no filtering is needed
      * @param aggregate an aggregate specifying how matching items must be 
bundled
@@ -677,7 +677,7 @@ public interface PersistenceService {
     /**
      * Aggregates item counts for the given type, optionally filtered by 
condition and
      * aggregated according to the specified {@link BaseAggregate}.
-     * This aggregate won't return the global count and should therefore be 
much faster than {@link #aggregateQuery(Condition, BaseAggregate, String)}
+     * This aggregate won't return the {@code _all} count and should therefore 
be much faster than {@link #aggregateQuery(Condition, BaseAggregate, String)}
      *
      * @param filter    the condition the items must match or {@code null} if 
no filtering is needed
      * @param aggregate an aggregate specifying how matching items must be 
bundled
diff --git 
a/rest/src/main/java/org/apache/unomi/rest/endpoints/QueryServiceEndPoint.java 
b/rest/src/main/java/org/apache/unomi/rest/endpoints/QueryServiceEndPoint.java
index d97b3ce79..6a6d3c058 100644
--- 
a/rest/src/main/java/org/apache/unomi/rest/endpoints/QueryServiceEndPoint.java
+++ 
b/rest/src/main/java/org/apache/unomi/rest/endpoints/QueryServiceEndPoint.java
@@ -92,7 +92,7 @@ public class QueryServiceEndPoint {
     /**
      * Returns property-value counts for an item type, optionally using an 
aggregate query.
      * <p>
-     * When {@code optimizedQuery} is {@code true}, the global document count 
is omitted for faster execution.
+     * When {@code optimizedQuery} is {@code true}, the {@code _all} count of 
the tenant's items of that type is omitted for faster execution.
      *
      * @param type the item type name from the class {@code ITEM_TYPE} field
      * @param property the property whose distinct values form aggregation 
buckets

Reply via email to