# Class AggregateQuery

java.lang.Object
com.codename1.health.AggregateQuery

public final class AggregateQuery extends Object

Describes a bucketed summary read against `HealthStore`.

    AggregateQuery q = new AggregateQuery()
            .addType(HealthDataType.STEPS)
            .addMetric(AggregateMetric.TOTAL)
            .setTimeRange(HealthTimeRange.calendarDays(7, TimeZone.getDefault()))
            .setBucket(HealthInterval.calendarDays(1, TimeZone.getDefault()));

##### Totals are not comparable across platforms

When a phone and a watch both record steps for the same walk, the store holds two overlapping sets of samples. HealthKit de-duplicates them in its statistics engine; Health Connect does not. The same query against the same person can therefore return roughly double on Android.

This API does not paper over that with a heuristic de-duplicator -- guessing which of two overlapping sources is authoritative is exactly the kind of silent wrongness health data cannot afford. Use `addSource(String)` to pin the query to the source you trust, and tell the user which device a figure came from.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `AggregateQuery()`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `AggregateQuery`
  `addMetric(AggregateMetric metric)`
  Adds a metric to compute.
  `AggregateQuery`
  `addSource(String bundleId)`
  Restricts the summary to one writing app -- see the double-counting warning on this class.
  `AggregateQuery`
  `addType(HealthDataType type)`
  Adds a type to summarize.
  `HealthInterval`
  `getBucket()`
  The bucket width, or null for one bucket over the whole range.
  `List<AggregateMetric>`
  `getMetrics()`
  The metrics this query computes.
  `List<String>`
  `getSources()`
  The source filter, empty when unrestricted.
  `HealthTimeRange`
  `getTimeRange()`
  The span this query summarizes.
  `List<HealthDataType>`
  `getTypes()`
  The types this query summarizes.
  `HealthUnit`
  `getUnit()`
  The requested unit, or null for canonical units.
  `static boolean`
  `isMeaningful(HealthDataType type, AggregateMetric metric)`
  Whether `metric` says anything true about `type`.
  `AggregateQuery`
  `setBucket(HealthInterval bucket)`
  Splits the range into buckets of this width.
  `AggregateQuery`
  `setTimeRange(HealthTimeRange timeRange)`
  The span to summarize.
  `AggregateQuery`
  `setUnit(HealthUnit unit)`
  Returns aggregated values in `unit` rather than each type's canonical unit.
  `void`
  `validate()`
  Validates the query and throws if it cannot be run.

  ### Methods inherited from class Object

  `clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Constructor Details

  - ### AggregateQuery

    public AggregateQuery()

- ## Method Details

  - ### addType

    public AggregateQuery addType(HealthDataType type)
    Adds a type to summarize. At least one is required.

  - ### getTypes

    public List<HealthDataType> getTypes()
    The types this query summarizes.

  - ### addMetric

    public AggregateQuery addMetric(AggregateMetric metric)
    Adds a metric to compute. At least one is required.

  - ### getMetrics

    public List<AggregateMetric> getMetrics()
    The metrics this query computes.

  - ### addSource

    public AggregateQuery addSource(String bundleId)
    Restricts the summary to one writing app -- see the double-counting warning on this class.

  - ### getSources

    public List<String> getSources()
    The source filter, empty when unrestricted.

  - ### setTimeRange

    public AggregateQuery setTimeRange(HealthTimeRange timeRange)
    The span to summarize. Required.

  - ### getTimeRange

    public HealthTimeRange getTimeRange()
    The span this query summarizes.

  - ### setBucket

    public AggregateQuery setBucket(HealthInterval bucket)

    Splits the range into buckets of this width. Leave unset for a single bucket covering the whole range.

    Prefer `HealthInterval.calendarDays(int,java.util.TimeZone)` over a fixed 24-hour width whenever the buckets are labelled with dates in your UI -- see `HealthInterval`.

  - ### getBucket

    public HealthInterval getBucket()
    The bucket width, or null for one bucket over the whole range.

  - ### setUnit

    public AggregateQuery setUnit(HealthUnit unit)
    Returns aggregated values in `unit` rather than each type's canonical unit.

  - ### getUnit

    public HealthUnit getUnit()
    The requested unit, or null for canonical units.

  - ### validate

    public void validate() throws HealthException

    Validates the query and throws if it cannot be run.

    ###### Throws

    - `HealthException`: `HealthError.INVALID_ARGUMENT` for a missing type, metric or range, or for a metric that is meaningless for the requested type; `HealthError.UNIT_MISMATCH` for an incompatible unit.
    Throws:
      `HealthException`

  - ### isMeaningful

    public static boolean isMeaningful(HealthDataType type, AggregateMetric metric)

    Whether `metric` says anything true about `type`.

    `AggregateMetric.COUNT` and `AggregateMetric.DURATION` apply to everything. Summing a discrete series -- the total of every body mass ever recorded -- and averaging a cumulative one -- the mean of arbitrarily-chunked step totals -- are both meaningless, so they are rejected rather than answered.