Repository: googleapis/java-datastore
Pull request #1861 (2025-05-19 15:12:22)

Added Generic getNumber Method to AggregationResult
feat: add getNumber to AggregationResult (https://github.com/googleapis/java-datastore/issues/1851)

cindy-peng: /gcbrun
st4sik: @cindy-peng 
I didn't explicitly write `50L` in the test because the method `integralValue` in `com.google.common.truth.Subject` already handles the conversion. 

Here's the relevant code:
```
private static long integralValue(Object o) {
        if (o instanceof Character) {
            return (long)(Character)o;
        } else if (o instanceof Number) {
            return ((Number)o).longValue();
        } else {
            throw new AssertionError(o + " must be either a Character or a Number.");
        }
    }
```

 As you can see, if the input is a `Number`, it automatically gets converted to `long` using `longValue()`. 
 So even if I pass 50 (an Integer), it will be treated as 50L internally.

Patch:
diff --git a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/AggregationResult.java b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/AggregationResult.java
index a5071d8d..1fdfa5bd 100644
--- a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/AggregationResult.java
+++ b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/AggregationResult.java
@@ -84,6 +84,26 @@ public class AggregationResult {
     }
   }
 
+  /**
+   * Returns a result value for the given alias.
+   *
+   * @param alias A custom alias provided in the query or an autogenerated alias in the form of
+   *     'property_\d'
+   * @return An aggregation result value as a {@link Number} for the given alias.
+   */
+  public Number getNumber(String alias) {
+    Value<?> value = properties.get(alias);
+    switch (value.getType()) {
+      case LONG:
+        return (Long) value.get();
+      case DOUBLE:
+        return (Double) value.get();
+      default:
+        throw new RuntimeException(
+            String.format("Unsupported type %s received for alias '%s'.", value.getType(), alias));
+    }
+  }
+
   @Override
   public boolean equals(Object o) {
     if (this == o) {


Test patch:
diff --git a/google-cloud-datastore/src/test/java/com/google/cloud/datastore/AggregationResultTest.java b/google-cloud-datastore/src/test/java/com/google/cloud/datastore/AggregationResultTest.java
index 592bfb36..84341f9d 100644
--- a/google-cloud-datastore/src/test/java/com/google/cloud/datastore/AggregationResultTest.java
+++ b/google-cloud-datastore/src/test/java/com/google/cloud/datastore/AggregationResultTest.java
@@ -77,5 +77,23 @@ public class AggregationResultTest {
     RuntimeException e2 =
         assertThrows(RuntimeException.class, () -> aggregationResult.getDouble("qty_avg"));
     assertThat(e2.getMessage()).isEqualTo("Unsupported type BOOLEAN received for alias 'qty_avg'.");
+
+    RuntimeException e3 =
+        assertThrows(RuntimeException.class, () -> aggregationResult.getNumber("qty_avg"));
+    assertThat(e3.getMessage()).isEqualTo("Unsupported type BOOLEAN received for alias 'qty_avg'.");
+  }
+
+  @Test
+  public void shouldGetDoubleAggregatedResultValueAsNumber() {
+    AggregationResult aggregationResult =
+        new AggregationResult(ImmutableMap.of("qty_avg", DoubleValue.of(45.9322)));
+    assertThat(aggregationResult.getNumber("qty_avg")).isEqualTo(45.9322);
+  }
+
+  @Test
+  public void shouldGetLongAggregatedResultValueAsNumber() {
+    AggregationResult aggregationResult =
+        new AggregationResult(ImmutableMap.of("count", LongValue.of(50)));
+    assertThat(aggregationResult.getNumber("count")).isEqualTo(50);
   }
 }