Dane zbiorcze

Interfejs Google Health API udostępnia specjalne punkty końcowe agregacji, które grupują i podsumowują dane o stanie zdrowia w przedziałach czasowych. Zamiast pobierać i sumować poszczególne nieprzetworzone rekordy na kliencie, użyj punktów końcowych agregacji, aby obliczyć dane (takie jak sumy, średnie, wartości minimalne i maksymalne) w uzgodnionym strumieniu danych:

  • Punkt końcowy rollUp agreguje punkty danych w fizycznych przedziałach czasu w strefie UTC, korzystając z konfigurowalnego czasu trwania okna w sekundach (windowSize).
  • Punkt końcowy dailyRollUp agreguje punkty danych z co najmniej 1 dnia kalendarzowego (windowSizeDays) przy użyciu czasu cywilnego względem lokalnego zegara użytkownika.

Oba punkty końcowe automatycznie uzgadniają nakładające się punkty danych na połączonych urządzeniach i wykluczają okresy, gdy urządzenie nie było noszone na nadgarstku, w przypadku typów danych z urządzeń do noszenia, które obsługują wykrywanie noszenia na nadgarstku.

Porównanie punktów końcowych agregacji

Wybierz punkt końcowy agregacji, który odpowiada sposobowi, w jaki aplikacja grupuje i wyświetla wskaźniki zdrowotne w postaci ciągów czasowych:

Funkcja rollUp punkt końcowy dailyRollUp punkt końcowy
Żądanie 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
Reprezentacja czasu Czas fizyczny w formacie UTC (startTime i endTime w formacie RFC 3339). Czas cywilny (start i end jako obiekty CivilDateTime).
Parametr okna windowSize (wymagany ciąg znaków, czas trwania w sekundach, minimum "1s"). windowSizeDays (opcjonalna liczba dni, domyślnie 1).
Obiekt odpowiedzi RollupDataPoint DailyRollupDataPoint
Porządkowanie odpowiedzi Odwrotny porządek chronologiczny (najnowsze okno jako pierwsze). Odwrotny porządek chronologiczny (najnowsze okno jako pierwsze).
Urządzenia Wykresy śróddzienne, histogramy godzinowe lub minutowe oraz analiza UTC o stałym czasie trwania. codzienne panele, trendy wielodniowe i podsumowania uwzględniające podróże między strefami czasowymi lub czas letni;

Oba punkty końcowe wymuszają maksymalne limity zakresu zapytań na podstawie typu danych:

  • Maksymalny zakres zapytania wynoszący 14 dni dotyczy tych wymiarów: calories-in-heart-rate-zone, heart-rate, active-minutes i total-calories.
  • W przypadku wszystkich innych obsługiwanych typów danych maksymalny zakres zapytania wynosi 90 dni.

Aby sprawdzić, które typy danych obsługują rollup i dailyRollup, zapoznaj się z dokumentacją typów danych interfejsu Google Health API.

Agregowanie w fizycznych przedziałach czasu

Użyj punktu końcowego rollUp, aby zagregować punkty danych w czasie fizycznym range (w strefie czasowej UTC) pogrupowane według czasu trwania okna w sekundach (windowSize).

Podczas wywoływania punktu końcowego rollUp podaj treść żądania w formacie JSON zawierającą przedział obustronnie domknięty range (startTime włącznie, endTime wyłącznie) i windowSize. Pamiętaj o tych wymaganiach dotyczących windowSize:

  • Czas trwania windowSize musi wynosić co najmniej 1 sekundę ("1s"). Interfejs API odrzuca czas trwania krótszy niż sekunda, równy zero lub ujemny, zwracając błąd 400 Bad Request (INVALID_ROLLUP_WINDOW).
  • Aby uniknąć nierównomiernego rozkładu danych zbiorczych w podzasobnikach, wybierz windowSize równy lub większy niż podstawowa rozdzielczość przechowywania danego typu danych (np. "60s" w przypadku 1-minutowych interwałów kroków). Więcej informacji znajdziesz w sekcji Okno podsumowania i rozdzielczość miejsca na dane.

Na przykład to żądanie podsumowuje liczbę kroków w 1-minutowych odstępach (60s):

Żądanie

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"
}

Odpowiedź

{
  "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"
      }
    },
...
  ]
}

Agregacja według dni kalendarzowych

Użyj punktu końcowego dailyRollUp, aby zagregować dane z jednego dnia kalendarzowego lub kilku dni (windowSizeDays). W treści żądania podaj czas cywilny w formacie zamkniętym-otwartym range (start i end). W zależności od typu danych punkt końcowy zwraca wartości zagregowane, takie jak suma lub średnia, dla każdego okna cywilnego.

dailyRollUp działa w czasie cywilnym, używając przesunięć UTC zarejestrowanych przy każdym punkcie danych, więc automatycznie uwzględnia zmienną długość dnia spowodowaną przejściem na czas letni lub podróżą między strefami czasowymi.

Na przykład to żądanie agreguje liczbę kroków w ciągu jednego dnia kalendarzowego (windowSizeDays: 1):

Żądanie

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
}

Odpowiedź

{
  "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"
      }
    }
  ]
}

Agreguj według rodziny źródeł danych

Zarówno rollUp, jak i dailyRollUp akceptują opcjonalne pole dataSourceFamily w treści żądania JSON, aby ograniczyć agregację do określonych grup źródłowych:

  • Opcja users/me/dataSourceFamilies/all-sources (domyślna) agreguje dane uzgodnione we wszystkich zarejestrowanych źródłach własnych i zewnętrznych.
  • Opcja users/me/dataSourceFamilies/google-wearables agreguje dane zarejestrowane przez urządzenia do śledzenia aktywności Google i Fitbit, z wyłączeniem danych zapisanych ręcznie i szacowanych przez telefon.
  • Opcja users/me/dataSourceFamilies/google-sources agreguje dane zbiorcze z własnych źródeł Google i Fitbita, w tym z trackerów, Health Connect i wpisów ręcznych w aplikacjach własnych.

Pełne wymagania dotyczące parametrów oraz przykłady żądań i odpowiedzi znajdziesz w sekcji Filtrowanie według rodziny źródeł danych w przewodniku po filtrowaniu danych.

Okno zestawienia i rozdzielczość miejsca na dane

Chociaż punkt końcowy rollUp akceptuje dowolną wartość windowSize wynoszącą co najmniej 1 sekundę ("1s"), różne typy danych rejestrują i zapisują pomiary z różnymi częstotliwościami próbkowania lub interwałami w podstawowym miejscu przechowywania. Na przykład dane dotyczące aktywności fizycznej z urządzeń do noszenia, takie jak steps, distance, active-minutes i active-energy-burned, są zwykle rejestrowane w interwałach 1-minutowych (60s).

W tabeli poniżej znajdziesz podstawowe rozdzielczości pamięci i minimalne zalecane wartości windowSize dla typowych typów danych:

Rozdzielczość pamięci Zalecane minimum: windowSize Typy danych
1 sekunda (1s) "1s" heart-rate
1 minuta (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

Podczas agregowania typów danych interwałowych punkt końcowy rollUp umieszcza każdy zarejestrowany punkt danych w zasobniku zawierającym startTime punktu danych. Interfejs API nie dzieli, nie interpoluje ani nie rozprowadza danych interwałowych między zasobnikami podinterwałowymi.

Jeśli określisz wartość windowSize, która jest mniejsza niż interwał przechowywania danych (np. poprosisz o 10-sekundowe okno dla steps przechowywanego w 1-minutowych interwałach):

  1. Pierwszy podzasób odpowiadający interwałowi startTime (np. od 10:00:00 do 10:00:10) otrzymuje łączną liczbę kroków z całej minuty (np. wszystkie 100 kroków zarejestrowanych w ciągu tej minuty).
  2. Pozostałe podzasobniki w tej samej minucie (od 10:00:10 do 10:00:20, od 10:00:20 do 10:00:30 itd.) nie otrzymują żadnych punktów danych, ponieważ w tych oknach nie zaczyna się żaden interwał.

Powoduje to powstawanie danych o dużych wahaniach, w których wartość całego interwału jest skoncentrowana w pierwszym podoknie, jak pokazano na rysunku 1.

Grupowanie podinterwałów w porównaniu z rozdzielczością przechowywania
Ilustracja 1. Grupowanie podinterwałów, w którym 1-minutowy interwał jest przypisany do pierwszego 10-sekundowego podzasobnika według startTime

Aby uzyskać równomiernie rozłożone i przydatne wartości zbiorcze, zawsze ustawiaj windowSize na czas trwania równy rozdzielczości pamięci docelowego typu danych lub większy (np. "60s" lub więcej w przypadku steps). Informacje o rozdzielczości pamięci i minimalnym zalecanym oknie zestawienia dla każdego typu danych znajdziesz w dokumentacji typów danych interfejsu Google Health API.

Grupowanie, gdy zakres nie jest wielokrotnością rozmiaru okna

Jeśli żądany zakres nie jest wielokrotnością windowSize (lub windowSizeDays), ostatni chronologiczny przedział jest obcinany w górnym punkcie końcowym zakresu i obejmuje czas krótszy niż rozmiar okna. Interfejs API akceptuje żądanie bez modyfikacji i nie wykonuje zaokrąglania, przesunięć czasowych ani interpolacji danych.

Aby objąć cały żądany zakres, interfejs API używa dzielenia z zaokrągleniem w górę do obliczenia łącznej liczby okien agregacji:

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

Każdy przedział zaczyna się sekwencyjnie od początku zakresu. Jeśli dodanie kolejnego okna o pełnym rozmiarze wykracza poza żądany czas zakończenia, ostatnie okno jest obcinane (ograniczane) do czasu zakończenia zakresu.

Jak działa grupowanie

Gdy żądasz zestawień z niepodzielnymi zakresami, interfejs API stosuje te reguły:

  • Grupowanie zaczyna się na początku żądanego zakresu (range.startTime lub range.start) i postępuje do przodu o rozmiar okna (windowSize lub windowSizeDays).
  • Ostatni przedział chronologiczny jest ograniczony na końcu żądanego zakresu (range.endTime lub range.end) i obejmuje krótszy okres niż żądany rozmiar okna.
  • Zwrócone obiekty RollupDataPoint lub DailyRollupDataPoint zawierają własne sygnatury czasowe rozpoczęcia i zakończenia, których możesz użyć do sprawdzenia rzeczywistego czasu trwania obciętego zasobnika.
  • Interfejs API zwraca dane zbiorcze w odwrotnej kolejności chronologicznej (od najnowszych), dlatego ostatni chronologicznie przedział (obcięty) pojawia się jako pierwszy element (index 0) na zwróconej liście.

Rysunek 2 pokazuje, jak interfejs API dzieli niepodzielny zakres na przedziały od range.startTime, ogranicza ostatni przedział do range.endTime i zwraca wynikowe przedziały w odwrotnej kolejności chronologicznej.

Grupowanie, obcinanie i porządkowanie odpowiedzi
Ilustracja 2. Grupowanie zbiorcze, obcinanie końca zakresu i odwrotna kolejność chronologiczna odpowiedzi

Przykładowy zakres 12 minut z 5-minutowym oknem

Załóżmy, że klient żąda zestawienia z zakresu 12 minut z 5-minutowym windowSize ("300s"):

  • Wartość range.startTime to 10:00:00Z.
  • Wartość range.endTime to 10:12:00Z, co daje łączny czas trwania wynoszący 12 minut.
  • Wartość windowSize to "300s" (5 minut).

Ponieważ 12 minut nie jest wielokrotnością 5 minut (12 = 5 * 2 + 2), interfejs API oblicza liczbę okien jako ceiling(12 / 5) = 3. W ten sposób powstają 3 chronologiczne zasobniki:

Zasobnik Interwał Czas trwania Stan okna
Zasobnik 1 [10:00:00Z, 10:05:00Z) 5 minut Pełne okno
Zasobnik 2 [10:05:00Z, 10:10:00Z) 5 minut Pełne okno
Zasobnik 3 [10:10:00Z, 10:12:00Z) 2 minuty Skrócono do range.endTime

Wpływ na wartości zagregowane

Ponieważ ostatnie okno chronologiczne jest krótsze, dane addytywne (takie jak suma lub liczba kroków) są mniejsze w skróconym przedziale ze względu na krótszy przedział czasu.

Jeśli użytkownik idzie w stałym tempie 100 kroków na minutę przez cały ten 12-minutowy zakres, przedziały zawierają następujące sumy:

  • Przedział 1 (10:00:00Z–10:05:00Z) rejestruje 500 kroków (5 minut przy 100 krokach na minutę).
  • Przedział 2 (10:05:00Z–10:10:00Z) rejestruje 500 kroków (5 minut przy 100 krokach na minutę).
  • Przedział 3 (od 10:10:00Z do 10:12:00Z) rejestruje 200 kroków (2 minuty po 100 kroków na minutę).

Mniejsza liczba kroków (200) w zasobniku 3 wynika z 2-minutowego czasu trwania skróconego okna, a nie ze spadku aktywności użytkownika. Podczas tworzenia wykresów lub analizowania tych danych znormalizuj liczby, używając jawnego czasu trwania każdego przedziału, aby uniknąć przedstawiania mylącego spadku aktywności użytkowników.

Rysunek 3 porównuje nieprzetworzone sumy kroków (countSum) ze znormalizowanymi pod względem czasu trwania wartościami w 3 grupach.

Porównanie nieprzetworzonych sum kroków w przedziałach i znormalizowanych współczynników kroków
Ilustracja 3. Nieprzetworzone sumy addytywne w porównaniu ze znormalizowanymi pod względem czasu trwania wartościami w przypadku obciętego zasobnika zbiorczego

Przykładowa odpowiedź interfejsu API pokazująca kolejność

Interfejs API zwraca wyniki w odwrotnej kolejności chronologicznej, więc obcięty zasobnik pojawia się jako pierwszy element na zwróconej liście:

{
  "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"
      }
    }
  ]
}