Dati aggregati

L'API Google Health fornisce endpoint di aggregazione dedicati che raggruppano e riassumono i riepiloghi salute in finestre temporali. Anziché recuperare e sommare i singoli record non elaborati sul client, utilizza gli endpoint di aggregazione per calcolare le metriche (come totali, medie, minimi e massimi) su uno stream di dati riconciliato:

  • L'endpoint rollUp aggrega i punti dati in intervalli di tempo fisici in UTC utilizzando una durata della finestra configurabile in secondi (windowSize).
  • L'endpoint dailyRollUp aggrega i punti dati in uno o più giorni di calendario (windowSizeDays) utilizzando l'ora civile relativa all'orologio locale dell'utente.

Entrambi gli endpoint riconciliano automaticamente i punti dati sovrapposti tra i dispositivi connessi ed escludono i periodi in cui il dispositivo non è stato indossato per i tipi di dati dei dispositivi indossabili che supportano il rilevamento al polso.

Confronta gli endpoint di aggregazione

Scegli l'endpoint di aggregazione che corrisponde al modo in cui la tua applicazione raggruppa e visualizza le metriche di salute delle serie temporali:

Funzionalità rollUp endpoint dailyRollUp endpoint
Richiesta HTTP POST https://health.googleapis.com/v4/users/me/dataTypes/data-type/dataPoints:rollUp POST https://health.googleapis.com/v4/users/me/dataTypes/data-type/dataPoints:dailyRollUp
Rappresentazione del tempo Ora fisica in UTC (startTime e endTime in formato RFC 3339). Ora civile (start e end come oggetti CivilDateTime).
Parametro finestra windowSize (durata della stringa obbligatoria in secondi, minimo "1s"). windowSizeDays (numero intero facoltativo di giorni, il valore predefinito è 1).
Oggetto risposta RollupDataPoint DailyRollupDataPoint
Ordinamento delle risposte Ordine cronologico inverso (la finestra più recente per prima). Ordine cronologico inverso (la finestra più recente per prima).
Ideale per Grafici infragiornalieri, istogrammi orari o al minuto e analisi UTC di durata fissa. Dashboard giornaliere, tendenze su più giorni e riepiloghi che tengono conto dei viaggi tra fusi orari o dell'ora legale.

Entrambi gli endpoint applicano limiti massimi per l'intervallo di query in base al tipo di dati:

  • A calories-in-heart-rate-zone, heart-rate, active-minutes e total-calories si applica un intervallo di query massimo di 14 giorni.
  • A tutti gli altri tipi di dati supportati si applica un intervallo di query massimo di 90 giorni.

Per verificare quali tipi di dati supportano rollup e dailyRollup, consulta il riferimento Tipi di dati dell'API Google Health.

Aggrega in base a intervalli di tempo fisici

Utilizza l'endpoint rollUp per aggregare i punti dati in un tempo fisico range (in UTC) raggruppati per una durata della finestra in secondi (windowSize).

Quando chiami l'endpoint rollUp, fornisci un corpo della richiesta JSON contenente l'intervallo chiuso-aperto range (startTime inclusivo, endTime esclusivo) e windowSize. Tieni presente i seguenti requisiti di windowSize:

  • La durata di windowSize deve essere di almeno 1 secondo ("1s"). L'API rifiuta durate inferiori al secondo, pari a zero o negative con un errore 400 Bad Request (INVALID_ROLLUP_WINDOW).
  • Per evitare una distribuzione non uniforme dei dati aggregati tra i bucket secondari, scegli un windowSize uguale o superiore alla risoluzione di archiviazione sottostante del tipo di dati (ad esempio "60s" per intervalli di passi di 1 minuto). Per maggiori dettagli, consulta Finestra di aggregazione e risoluzione dello spazio di archiviazione.

Ad esempio, la seguente richiesta aggrega i conteggi dei passi in intervalli di 1 minuto (60s):

Richiesta

POST https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints:rollUp
Authorization: Bearer access-token
Accept: application/json

{
  "range": {
    "startTime": "2026-02-17T17:00:00Z",
    "endTime": "2026-02-17T17:59:59Z"
  },
  "windowSize": "60s"
}

Risposta

{
  "rollupDataPoints": [
    {
      "startTime": "2026-02-17T17:55:00Z",
      "endTime": "2026-02-17T17:56:00Z",
      "steps": {
        "countSum": "72"
      }
    },
    {
      "startTime": "2026-02-17T17:54:00Z",
      "endTime": "2026-02-17T17:55:00Z",
      "steps": {
        "countSum": "85"
      }
    },
...
  ]
}

Aggrega per giorni di calendario

Utilizza l'endpoint dailyRollUp per aggregare i dati in un singolo giorno di calendario o in più giorni (windowSizeDays). Specifica l'ora civile chiusa-aperta range (start e end) nel corpo della richiesta. A seconda del tipo di dati, l'endpoint restituisce valori aggregati come la somma o la media per ogni finestra civile.

Poiché dailyRollUp opera sull'ora civile utilizzando gli offset UTC registrati con ogni punto dati, riconcilia automaticamente le lunghezze variabili dei giorni causate dalle transizioni dell'ora legale o dai viaggi tra fusi orari.

Ad esempio, la seguente richiesta aggrega i conteggi dei passi in un singolo giorno civile (windowSizeDays: 1):

Richiesta

POST https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints:dailyRollUp
Authorization: Bearer access-token
Accept: application/json

{
  "range": {
    "start": {
      "date": {
        "year": 2026,
        "month": 2,
        "day": 26
      },
      "time": {
        "hours": 0,
        "minutes": 0,
        "seconds": 0,
        "nanos": 0
      }
    },
    "end": {
      "date": {
        "year": 2026,
        "month": 2,
        "day": 26
      },
      "time": {
        "hours": 23,
        "minutes": 59,
        "seconds": 59,
        "nanos": 0
      }
    }
  },
  "windowSizeDays": 1
}

Risposta

{
  "rollupDataPoints": [
    {
      "civilStartTime": {
        "date": {
          "year": 2026,
          "month": 2,
          "day": 26
        },
        "time": {}
      },
      "civilEndTime": {
        "date": {
          "year": 2026,
          "month": 2,
          "day": 26
        },
        "time": {
          "hours": 23,
          "minutes": 59,
          "seconds": 59
        }
      },
      "steps": {
        "countSum": "3822"
      }
    }
  ]
}

Aggrega per famiglia di origini dati

Sia rollUp che dailyRollUp accettano un campo dataSourceFamily facoltativo nel corpo della richiesta JSON per limitare l'aggregazione a gruppi di origine specifici:

  • L'opzione users/me/dataSourceFamilies/all-sources (predefinita) aggrega i dati riconciliati in tutte le origini proprietarie e di terze parti registrate.
  • L'opzione users/me/dataSourceFamilies/google-wearables aggrega i dati registrati dai tracker indossabili Google e Fitbit, esclusi i dati registrati manualmente e stimati dallo smartphone.
  • L'opzione users/me/dataSourceFamilies/google-sources aggrega i dati provenienti da fonti proprietarie di Google e Fitbit, inclusi tracker indossabili, Connessione Salute e voci manuali nelle app proprietarie.

Per i requisiti completi dei parametri e gli esempi di richieste e risposte, consulta Filtra per famiglia di origini dati nella guida Filtra i dati.

Finestra di aggregazione e risoluzione dello spazio di archiviazione

Sebbene l'endpoint rollUp accetti qualsiasi windowSize di 1 secondo ("1s") o superiore, i diversi tipi di dati registrano e rendono persistenti le misurazioni con frequenze di campionamento o durate degli intervalli diverse nello spazio di archiviazione sottostante. Ad esempio, le metriche relative all'attività fisica dei dispositivi indossabili, come steps, distance, active-minutes e active-energy-burned, vengono in genere registrate a intervalli di 1 minuto (60s).

La tabella seguente elenca le risoluzioni di archiviazione sottostanti e i valori windowSize minimi consigliati per i tipi di dati comuni:

Risoluzione dello spazio di archiviazione Minimo consigliato: windowSize Tipi di dati
1 secondo (1s) "1s" heart-rate
1 minuto (60s) "60s" active-energy-burned, active-minutes, active-zone-minutes, altitude, calories-in-heart-rate-zone, distance, floors, steps, time-in-heart-rate-zone, total-calories

Quando aggrega i tipi di dati di intervallo, l'endpoint rollUp inserisce ogni punto dati registrato nel bucket contenente il startTime del punto dati. L'API non suddivide, interpola o distribuisce i dati degli intervalli tra i bucket di intervalli secondari.

Se specifichi un valore windowSize inferiore all'intervallo di archiviazione dei dati sottostante (ad esempio, richiedi una finestra di 10 secondi per steps archiviati a intervalli di 1 minuto):

  1. Il primo bucket secondario corrispondente all'intervallo startTime (ad esempio, 10:00:00-10:00:10) riceve il conteggio accumulato dell'intero minuto (ad esempio, tutti i 100 passi registrati per quel minuto).
  2. I bucket secondari rimanenti nello stesso minuto (da 10:00:10 a 10:00:20, da 10:00:20 a 10:00:30 e così via) non ricevono punti dati, perché nessun intervallo inizia all'interno di queste finestre.

In questo modo si ottengono dati con picchi in cui il valore dell'intero intervallo è concentrato nella prima finestra secondaria, come mostrato nella Figura 1.

Bucketing di aggregazione degli intervalli secondari rispetto alla risoluzione dello spazio di archiviazione
Figura 1: raggruppamento dei bucket di intervalli secondari in cui un intervallo di 1 minuto viene assegnato al primo bucket secondario di 10 secondi in base a startTime

Per ottenere aggregati distribuiti in modo uniforme e significativi, imposta sempre windowSize su una durata uguale o superiore alla risoluzione di archiviazione sottostante del tipo di dati target (ad esempio, "60s" o superiore per steps). Per la risoluzione di archiviazione e la finestra di aggregazione minima consigliata per ogni tipo di dati, consulta il riferimento Tipi di dati dell'API Google Health.

Bucketing quando l'intervallo non è un multiplo della dimensione della finestra

Se l'intervallo richiesto non è un multiplo esatto di windowSize (o windowSizeDays), il bucket cronologico finale viene troncato in corrispondenza dell'endpoint superiore dell'intervallo e copre una durata inferiore alle dimensioni della finestra. L'API accetta la richiesta senza modifiche e non esegue arrotondamenti, spostamenti temporali o interpolazioni dei dati.

Per coprire l'intero intervallo richiesto, l'API utilizza la divisione per eccesso per calcolare il numero totale di finestre di aggregazione:

Number of windows = ceiling(Range duration / Window size)

Ogni bucket inizia in sequenza dall'inizio dell'intervallo. Se l'aggiunta di un'altra finestra di dimensioni massime si estende oltre l'ora di fine richiesta, la finestra finale viene troncata (bloccata) all'ora di fine dell'intervallo.

Come funziona il bucketing

Quando richiedi i rollup con intervalli non divisibili, l'API applica le seguenti regole:

  • Il bucketing inizia all'inizio dell'intervallo richiesto (range.startTime o range.start) e procede in avanti in base alle dimensioni della finestra (windowSize o windowSizeDays).
  • Il bucket cronologico finale viene bloccato alla fine dell'intervallo richiesto (range.endTime o range.end), coprendo una durata inferiore rispetto alla dimensione della finestra richiesta.
  • Gli oggetti RollupDataPoint o DailyRollupDataPoint restituiti includono i propri timestamp di inizio e fine espliciti, che puoi utilizzare per esaminare la durata effettiva del bucket troncato.
  • Poiché l'API restituisce i dati di aggregazione in ordine cronologico inverso (dal più recente al meno recente), il bucket cronologico finale (il bucket troncato) viene visualizzato come primo elemento (index 0) nell'elenco restituito.

La Figura 2 illustra in che modo l'API raggruppa un intervallo non divisibile in avanti da range.startTime, blocca il bucket finale in range.endTime e restituisce i bucket risultanti in ordine cronologico inverso.

Raggruppamento, troncamento e ordinamento delle risposte dei rollup
Figura 2: bucketing di aggregazione, troncamento di fine intervallo e ordinamento cronologico inverso delle risposte

Esempio di intervallo di 12 minuti con una finestra di 5 minuti

Supponiamo che un client richieda un rollup su un intervallo di 12 minuti con un windowSize ("300s") di 5 minuti:

  • Il valore range.startTime è 10:00:00Z.
  • Il valore range.endTime è 10:12:00Z, per una durata totale di 12 minuti.
  • Il valore windowSize è "300s" (5 minuti).

Poiché 12 minuti non è un multiplo esatto di 5 minuti (12 = 5 * 2 + 2), l'API calcola il numero di finestre come ceiling(12 / 5) = 3. In questo modo vengono creati tre bucket cronologici:

Bucket Intervallo Durata Stato intervallo
Bucket 1 [10:00:00Z, 10:05:00Z) 5 minuti Finestra intera
Bucket 2 [10:05:00Z, 10:10:00Z) 5 minuti Finestra intera
Bucket 3 [10:10:00Z, 10:12:00Z) 2 minuti Troncato a range.endTime

Impatto sui valori aggregati

Poiché la finestra cronologica finale ha una durata inferiore, le metriche additive (come la somma o il conteggio dei passi) sono inferiori nel bucket troncato a causa dell'intervallo di tempo più breve.

Se un utente cammina a un ritmo costante di 100 passi al minuto durante l'intero intervallo di 12 minuti, i bucket contengono i seguenti totali:

  • Il bucket 1 (da 10:00:00Z a 10:05:00Z) registra 500 passi (5 minuti a 100 passi al minuto).
  • Il bucket 2 (da 10:05:00Z a 10:10:00Z) registra 500 passi (5 minuti a 100 passi al minuto).
  • Il bucket 3 (da 10:10:00Z a 10:12:00Z) registra 200 passi (2 minuti a 100 passi al minuto).

Il numero di passi inferiore di 200 passi nel bucket 3 è dovuto alla durata di 2 minuti della finestra troncata, non a un calo dell'attività dell'utente. Quando tracci o analizzi questi dati, normalizza i conteggi utilizzando la durata esplicita di ogni bucket per evitare di presentare un calo fuorviante dell'attività utente.

La Figura 3 confronta i totali dei passi additivi non elaborati (countSum) con i tassi normalizzati in base alla durata nei tre bucket.

Confronto tra i totali dei passi non elaborati e i tassi di passi normalizzati
Figura 3: totali additivi non elaborati rispetto alle frequenze normalizzate in base alla durata per un bucket di aggregazione troncato

Esempio di risposta dell'API che mostra l'ordinamento

Poiché l'API restituisce i risultati in ordine cronologico inverso, il bucket troncato viene visualizzato come primo elemento nell'elenco restituito:

{
  "rollupDataPoints": [
    {
      "startTime": "2026-08-20T10:10:00Z",
      "endTime": "2026-08-20T10:12:00Z",
      "steps": {
        "countSum": "200"
      }
    },
    {
      "startTime": "2026-08-20T10:05:00Z",
      "endTime": "2026-08-20T10:10:00Z",
      "steps": {
        "countSum": "500"
      }
    },
    {
      "startTime": "2026-08-20T10:00:00Z",
      "endTime": "2026-08-20T10:05:00Z",
      "steps": {
        "countSum": "500"
      }
    }
  ]
}