Z tej sekcji dowiesz się, jak wysyłać do Google pilne aktualizacje plików danych. Interfejs przyrostowy interfejsu API umożliwia aktualizowanie i usuwanie elementów w kanałach niemal w czasie rzeczywistym.
Ta funkcja jest przeznaczona głównie do aktualizacji, których nie można przewidzieć, takich jak zamknięcie awaryjne. Każda zmiana przesłana za pomocą interfejsu przyrostowego interfejsu API powinna zostać wprowadzona najpóźniej w ciągu tygodnia. Jeśli zmiana nie musi zostać od razu odzwierciedlona, możesz użyć aktualizacji zbiorczej. Zmiany przyrostowe są przetwarzane w ciągu nie więcej niż 5 minut.
Konfiguracja
Aby zaimplementować aktualizacje przyrostowe, wykonaj te czynności:
- Aby utworzyć projekt, wykonaj czynności opisane w sekcji Tworzenie i konfigurowanie projektu.
- Aby utworzyć konto usługi, wykonaj czynności opisane w sekcji Konfigurowanie konta usługi. Pamiętaj, że aby dodać rolę „edytujący” i „edytujący” konto usługi, musisz być właścicielem
- (Opcjonalnie, ale zalecane) Zainstaluj bibliotekę klienta Google w wybranym języku, aby ułatwić korzystanie z protokołu OAuth 2.0 podczas wywoływania interfejsu API. W podanych niżej przykładach kodu wykorzystywane są te biblioteki. W przeciwnym razie musisz ręcznie obsługiwać wymiany tokenów zgodnie z opisem w artykule Korzystanie z OAuth 2.0 do dostępu do interfejsów API Google.
Punkt końcowy
Aby powiadomić Google o aktualizacji, wyślij żądanie HTTP POST do interfejsu Incremental Updates API i ładuj aktualizacje i dodatki. Schemat zasobów reklamowych określa, który punkt końcowy chcesz wysłać żądanie:
Zasoby reklamowe w wersji 2
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/TYPE/ENTITY_ID:push
Zasoby reklamowe w wersji 1
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/ENTITY_ID:push
Aby usunąć jednostkę, wyślij żądanie HTTP DELETE do tego punktu końcowego odpowiadającego Twojemu schematowi zasobów reklamowych:
Zasoby reklamowe w wersji 2
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/TYPE/ENTITY_ID?entity.vertical=FOODORDERING&delete_time=DELETE_TIME
Zasoby reklamowe w wersji 1
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/ENTITY_ID?entity.vertical=FOODORDERING&delete_time=DELETE_TIME
Zastąp następujące żądania w tych żądaniach:
- PROJECT_ID: identyfikator projektu Google Cloud powiązanego z projektem utworzonym w artykule Tworzenie i konfigurowanie projektu.
- TYPE (tylko schemat asortymentu w wersji 2): typ encji (usługa
@type
) obiektu w pliku danych, który chcesz zaktualizować. - ENTITY_ID: identyfikator podmiotu uwzględnionego w ładunku. Pamiętaj, aby zakodować identyfikator jednostki w adresie URL.
- DELETE_TIME (tylko usunięcie punktu końcowego): pole opcjonalne wskazujące, kiedy element został usunięty w systemach (domyślnie jest to miejsce, w którym zostało odebrane żądanie). Wartość czasu nie może być w przyszłości. Gdy wysyłasz encję za pomocą wywołania przyrostowego, obsługi wersji elementu używa też pola
delete_time
w przypadku wywołania usunięcia. Sformatuj tę wartość jakoyyyy-mm-ddTHH:mm:ssZ
Masz na przykład projekt o identyfikatorze "delivery-provider-id" wykorzystujący schemat zasobów reklamowych v2. Chcesz wprowadzić zmiany w restauracji o typie elementu „"MenuSection"” i identyfikatorze „"menuSection_122"”. Punktem końcowym, w którym aktualizacje danych mogą być:
https://actions.googleapis.com/v2/apps/delivery-provider-id/entities/MenuSection/menuSection_122:push
Aby usunąć tę samą encję, wykonaj to wywołanie HTTP DELETE API:
https://actions.googleapis.com/v2/apps/delivery-provider-id/entities/MenuSection/menuSection_122?entity.vertical=FOODORDERING
Żądania w piaskownicy
W przypadku żądań w trybie piaskownicy postępuj zgodnie ze wskazówkami podanymi w sekcji Punkt końcowy powyżej, ale wysyłaj żądania do /v2/sandbox/apps/
zamiast do /v2/apps/
. Na przykład żądanie usunięcia danych w piaskownicy dla schematu zasobów reklamowych v2 ma taką strukturę:
https://actions.googleapis.com/v2/sandbox/apps/PROJECT_ID/entities/TYPE/ENTITY_ID?entity.vertical=FOODORDERING&delete_time=DELETE_TIME
Aktualizacje i dodania
Codzienne pliki danych zbiorczych powinny też zawierać wszelkie zmiany przesłane przez ten interfejs API. W przeciwnym razie aktualizacje zbiorcze zastąpią przyrostowe zmiany.
Ładunek
Każde żądanie POST musi zawierać parametry żądania w ładunku JSON zawierającym uporządkowane dane dowolnego typu encji wymienionego w schemacie asortymentu.
Plik JSON powinien wyglądać tak samo jak w pliku danych zbiorczych, z tymi różnicami:
- Rozmiar ładunku nie powinien przekraczać 5 MB. Podobnie jak w przypadku kanałów wsadowych, zalecamy usunięcie spacji, aby dopasować więcej danych.
- Koperta jest taka:
{ "entity": { "data":"ENTITY_DATA", "vertical":"FOODORDERING" }, "update_time":"UPDATE_TIMESTAMP" }
W powyższym ładunku zastąp te elementy:
- ENTITY_DATA: element w formacie JSON zserializowany jako ciąg znaków. Encja JSON-LD musi być przekazywana jako ciąg znaków w polu
data
. - UPDATE_TIMESTAMP (opcjonalnie): sygnatura czasowa aktualizacji elementu w Twoich systemach. Wartość czasu nie może być w przyszłości. Domyślna sygnatura czasowa oznacza moment, w którym Google otrzymuje żądanie. Gdy wysyłasz encję za pomocą żądania przyrostowego, obsługa wersji obejmuje też pole
update_time
w przypadku żądania dodania/aktualizacji.
Aktualizowanie encji
Przykład 1. Aktualizowanie restauracji
Załóżmy, że musisz pilnie zaktualizować numer telefonu restauracji. Aktualizacja zawiera kod JSON całej restauracji.
Rozważ użycie zbiorczego pliku danych podobnego do tego:
{ "@type": "Restaurant", "@id": "restaurant12345", "name": "Some Restaurant", "url": "https://www.provider.com/somerestaurant", "telephone": "+16501234567", "streetAddress": "345 Spear St", "addressLocality": "San Francisco", "addressRegion": "CA", "postalCode": "94105", "addressCountry": "US", "latitude": 37.472842, "longitude": -122.217144 }
Następnie przyrostowa aktualizacja POST w protokole HTTP będzie wyglądać tak:
POST v2/apps/provider-project/entities/Restaurant/restaurant12345:push Host: actions.googleapis.com Content-Type: application/ld+json { "entity": { "data": { "@type": "Restaurant", "@id": "restaurant12345", "name": "Some Restaurant", "url": "https://www.provider.com/somerestaurant", "telephone": "+16501235555", "streetAddress": "345 Spear St", "addressLocality": "San Francisco", "addressRegion": "CA", "postalCode": "94105", "addressCountry": "US", "latitude": 37.472842, "longitude": -122.217144 }, "vertical": "FOODORDERING" } }
Przykład 2. Aktualizacja ceny elementu menu
Załóżmy, że chcesz zmienić cenę pozycji menu. Tak jak w przykładzie 1, aktualizacja musi zawierać kod JSON dla całego elementu najwyższego poziomu (menu), a plik danych używa schematu zasobów reklamowych w wersji 1.
Rozważ użycie zbiorczego pliku danych podobnego do tego:
{ "@type": "MenuItemOffer", "@id": "menuitemoffer6680262", "sku": "offer-cola", "menuItemId": "menuitem896532", "price": 3.00, "priceCurrency": "USD" }
Wtedy przyrostowa aktualizacja za pomocą metody POST będzie wyglądać tak:
POST v2/apps/provider-project/entities/MenuItemOffer/menuitemoffer6680262:push Host: actions.googleapis.com Content-Type: application/ld+json { "entity": { "data": { "@type": "MenuItemOffer", "@id": "menuitemoffer6680262", "sku": "offer-cola", "menuItemId": "menuitem896532", "price": 1.00, "priceCurrency": "USD" }, "vertical": "FOODORDERING" } }
Dodawanie encji
Aby dodać elementy, nie używaj aktualizacji zasobów. Zamiast tego użyj procesu zbiorczego pliku danych w sposób opisany w schemacie zasobów reklamowych v2.
Usuwanie encji
Aby usunąć encje najwyższego poziomu, użyj lekko zmodyfikowanego punktu końcowego i użyj w żądaniu żądania HTTP DELETE zamiast HTTP POST.
Nie używaj protokołu HTTP DELETE do usunięcia elementu podrzędnego w jednostce najwyższego poziomu, np. do elementu menu. Zamiast tego potraktuj usunięcie encji jako aktualizację elementu najwyższego poziomu, z którego ten element został usunięty z odpowiedniej listy lub parametru.
Przykład 1. Usuwanie elementu najwyższego poziomu
Weź pod uwagę sytuację, w której chcesz usunąć restaurację, która korzysta ze schematu zasobów reklamowych v1. Musisz też usunąć powiązane z nim usługi i menu.
Przykładowy punkt końcowy elementu menu o identyfikatorze&https://www.provider.com/restauracja/menu/nr":
DELETE v2/apps/delivery-provider-id/entities/https%3A%2F%2Fwww.provider.com%2Frestaurant%2Fmenu%2Fnr?entity.vertical=FOODORDERING
Host: actions.googleapis.com
Przykładowy punkt końcowy dla elementu restauracji o identyfikatorze&https://www.provider.com/restauracja/nr":
DELETE v2/apps/delivery-provider-id/entities/https%3A%2F%2Fwww.provider.com%2Frestaurant%2Fnr?entity.vertical=FOODORDERING
Host: actions.googleapis.com
Przykładowy punkt końcowy dla usługi o identyfikatorze ID:
DELETE v2/apps/delivery-provider-id/entities/https%3A%2F%2Fwww.provider.com%2Frestaurant%2Fservice%2Fnr?entity.vertical=FOODORDERING
Host: actions.googleapis.com
}
Przykład 2. Usuwanie podmiotów
Aby usunąć element podrzędny z elementu najwyższego poziomu, wyślij go do elementu nadrzędnego, który został usunięty z odpowiedniego pola. W przykładzie poniżej założono, że plik danych korzysta ze schematu zasobów reklamowych v1.
Aby na przykład usunąć obszar działalności, zaktualizuj obszar o usłudze usunięty z listy areaServed
.
POST v2/apps/delivery-provider-id/entities/https%3A%2F%2Fwww.provider.com%2Frestaurant%2Fservice%2Fnr:push
Host: actions.googleapis.com
Content-Type: application/ld+json
{
"entity": {
// Note: "data" is not serialized as a string in our example for readability.
"data": {
"@type": "Service",
"provider": {
"@type": "Restaurant",
"@id": "https://www.provider.com/restaurant/nr"
},
"areaServed": [
{
"@type": "GeoCircle",
"geoMidpoint": {
"@type": "GeoCoordinates",
"latitude": "42.362757",
"longitude": "-71.087109"
},
"geoRadius": "10000"
}
// area2 is removed.
]
...
},
"vertical": "FOODORDERING"
}
}
Kody odpowiedzi interfejsu API
Udane wywołanie nie oznacza, że plik danych jest prawidłowy lub prawidłowy, tylko że zostało wykonane wywołanie interfejsu API. Udane połączenia otrzymują kod odpowiedzi HTTP 200 oraz pusty tekst odpowiedzi:
{}
W przypadku awarii kod odpowiedzi HTTP nie będzie wynosił 200, a treść odpowiedzi będzie wskazywać błąd.
Jeśli na przykład użytkownik ustawił wartość "vertical" w danych koperty na FAKE_VERTICAL
, otrzymasz ten komunikat:
{
"error": {
"code": 400,
"message": "Invalid value at 'entity.vertical' (TYPE_ENUM), \"FAKE_VERTICAL\"",
"status": "INVALID_ARGUMENT",
"details": [
{
"@type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "entity.vertical",
"description": "Invalid value at 'entity.vertical' (TYPE_ENUM), \"FAKE_VERTICAL\""
}
]
}
]
}
}
Przykładowy kod
Poniżej znajdziesz kilka przykładów użycia interfejsu Incremental Updates API w różnych językach. W tych przykładach używane są biblioteki uwierzytelniania Google i przyjmowane są pliki danych za pomocą schematu zasobów reklamowych v1. Informacje o alternatywnych rozwiązaniach znajdziesz w artykule Korzystanie z OAuth 2.0 dla aplikacji serwer-serwer.
Aktualizowanie encji
Node.js
Ten kod używa biblioteki uwierzytelniania Google na potrzeby środowiska Node.js.
const {auth} = require('google-auth-library') const request = require('request'); // The service account client secret file downloaded from the Google Cloud Console const serviceAccountJson = require('./service-account.json') // entity.json is a file that contains the entity data in json format const entity = require('./entity.json') const ENTITY_ID = 'restaurant/http://www.provider.com/somerestaurant' const PROJECT_ID = 'your-project-id' /** * Get the authorization token using a service account. */ async function getAuthToken() { let client = auth.fromJSON(serviceAccountJson) client.scopes = ['https://www.googleapis.com/auth/assistant'] const tokens = await client.authorize() return tokens.access_token; } /** * Send an incremental update to update or add an entity */ async function updateEntity(entityId, entity) { const token = await getAuthToken() request.post({ headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, url: `https://actions.googleapis.com/v2/apps/${PROJECT_ID}/entities/${encodeURIComponent(entityId)}:push`, body: { entity: { data: JSON.stringify(entity), vertical: 'FOODORDERING', } }, json: true }, (err, res, body) => { if (err) { return console.log(err); } console.log(`Response: ${JSON.stringify(res)}`) }) } updateEntity(ENTITY_ID, entity)
Python
Ten kod używa biblioteki uwierzytelniania Google na potrzeby Pythona.
from google.oauth2 import service_account from google.auth.transport.requests import AuthorizedSession import json import urllib PROJECT_ID = 'your-project-id' ENTITY_ID = 'restaurant/http://www.provider.com/somerestaurant' ENDPOINT = 'https://actions.googleapis.com/v2/apps/%s/entities/%s:push' % ( PROJECT_ID, urllib.quote(ENTITY_ID, '')) # service-account.json is the service account client secret file downloaded from the # Google Cloud Console credentials = service_account.Credentials.from_service_account_file( 'service-account.json') scoped_credentials = credentials.with_scopes( ['https://www.googleapis.com/auth/assistant']) authed_session = AuthorizedSession(scoped_credentials) # Retrieving the entity update_file = open("entity.json") #JSON file containing entity data in json format. data = update_file.read() # Populating the entity with wrapper entity = {} entity['data'] = data #entity JSON-LD serialized as string entity['vertical'] = 'FOODORDERING' request = {} request['entity'] = entity response = authed_session.post(ENDPOINT, json=request) print(response.text) #if successful, will be '{}'
Java
Ten kod używa biblioteki uwierzytelniania Google na potrzeby Javy.
private static final String PROJECT_ID = "your-project-id"; private static final String ENTITY_ID = "http://www.provider.com/somerestaurant"; /** * Get the authorization token using a service account. */ private static String getAuthToken() { InputStream serviceAccountFile = Example.class.getClassLoader().getResourceAsStream("service-account.json"); ServiceAccountCredentials.Builder credentialsSimpleBuilder = ServiceAccountCredentials.fromStream(serviceAccountFile).toBuilder(); credentialsSimpleBuilder.setScopes(ImmutableList.of("https://www.googleapis.com/auth/assistant")); AccessToken accessToken = credentialsSimpleBuilder.build().refreshAccessToken(); return accessToken.getTokenValue(); } /** * Send an incremental update to update or add an entity. * @param entityId The id of the entity to update. * @param entity the json of the entity to be updated. */ public void updateEntity(String entityId, JSONObject entity) { String authToken = getAuthToken(); String endpoint = String.format( "https://actions.googleapis.com/v2/apps/%s/entities/%s:push", PROJECT_ID, URLEncoder.encode(entityId, "UTF-8")); JSONObject data = new JSONObject(); data.put("data", entity.toString()); data.put("vertical", "FOODORDERING"); JSONObject jsonBody = new JSONObject(); jsonBody.put("entity", data); // Execute POST request executePostRequest(endpoint, authToken, jsonBody); }
Usuwanie encji
Node.js
Ten kod używa biblioteki uwierzytelniania Google na potrzeby środowiska Node.js.
const {auth} = require('google-auth-library') const request = require('request'); // The service account client secret file downloaded from the Google Cloud Console const serviceAccountJson = require('./service-account.json') // entity.json is a file that contains the entity data in json format const entity = require('./entity.json') const ENTITY_ID = 'restaurant/http://www.provider.com/somerestaurant' const PROJECT_ID = 'your-project-id' /** * Get the authorization token using a service account. */ async function getAuthToken() { let client = auth.fromJSON(serviceAccountJson) client.scopes = ['https://www.googleapis.com/auth/assistant'] const tokens = await client.authorize() return tokens.access_token; } /** * Send an incremental update to delete an entity */ async function deleteEntity(entityId) { const token = await getAuthToken() request.delete({ headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, url: `https://actions.googleapis.com/v2/apps/${PROJECT_ID}/entities/${encodeURIComponent(entityId)}?entity.vertical=FOODORDERING`, body: {}, json: true }, (err, res, body) => { if (err) { return console.log(err); } console.log(`Response: ${JSON.stringify(res)}`) }) } deleteEntity(ENTITY_ID)
Python
Ten kod używa biblioteki uwierzytelniania Google na potrzeby Pythona.
from google.oauth2 import service_account from google.auth.transport.requests import AuthorizedSession import json import urllib # Service config PROJECT_ID = 'your-project-id' ENTITY_ID = 'restaurant/http://www.provider.com/somerestaurant' DELETE_TIME = '2018-04-07T14:30:00-07:00' ENDPOINT = 'https://actions.googleapis.com/v2/apps/%s/entities/%s?entity.vertical=FOODORDERING&delete_time=%s' % ( PROJECT_ID, urllib.quote(ENTITY_ID, ''), urllib.quote(DELETE_TIME, '')) # service-account.json is the service account client secret file downloaded from the # Google Cloud Console credentials = service_account.Credentials.from_service_account_file( 'service-account.json') scoped_credentials = credentials.with_scopes( ['https://www.googleapis.com/auth/assistant']) authed_session = AuthorizedSession(scoped_credentials) response = authed_session.delete(ENDPOINT) print(response.text) #if successful, will be '{}'
Java
Ten kod używa biblioteki uwierzytelniania Google na potrzeby Javy.
private static final String PROJECT_ID = "your-project-id"; private static final String ENTITY_ID = "restaurant/http://www.provider.com/somerestaurant"; /** * Get the authorization token using a service account. */ private static String getAuthToken() { InputStream serviceAccountFile = Example.class.getClassLoader().getResourceAsStream("service-account.json"); ServiceAccountCredentials.Builder credentialsSimpleBuilder = ServiceAccountCredentials.fromStream(serviceAccountFile).toBuilder(); credentialsSimpleBuilder.setScopes(ImmutableList.of("https://www.googleapis.com/auth/assistant")); AccessToken accessToken = credentialsSimpleBuilder.build().refreshAccessToken(); return accessToken.getTokenValue(); } /** * Send an incremental update to delete an entity. * @param entityId The id of the entity to delete. */ public void deleteEntity(String entityId) { String authToken = getAuthToken(); String endpoint = String.format( "https://actions.googleapis.com/v2/apps/%s/entities/%s?entity.vertical=FOODORDERING", PROJECT_ID, URLEncoder.encode(entityId, "UTF-8")); // Execute DELETE request System.out.println(executeDeleteRequest(endpoint, authToken)); }
Przypadki użycia
Wybrane przykłady zastosowania aktualizacji przyrostowych, pełnych aktualizacji pliku danych i wysokiej zawartości treści w wywołaniu interfejsu API:
Scenariusz | Element najwyższego poziomu | Opis i efekty |
---|---|---|
Wyłączanie usługi | DisabledService |
Usługę należy wyłączyć z nieprzewidzianych powodów. Aktualizacje przyrostowe: wyślij odpowiedni element Pełne kanały: pamiętaj, aby zaktualizować element z pełnych kanałów, tak aby |
Ten produkt jest niedostępny | Menu |
Aktualizacje przyrostowe: w przypadku danego elementu MenuItem ustaw o wartości offer.inventoryLevel wartość , a pozostałe dane bez zmian. |
Zmiana ceny elementu menu | Menu |
Aktualizacje przyrostowe: w przypadku elementu MenuItem z offer.price ustaw nową cenę dla danego elementu MenuItem i wszystkie pozostałe dane bez zmian. |
Dodaj nowy element najwyższego poziomu Dotyczy tylko typów |
Menu , Restaurant , Service |
Możesz na przykład dodać nowe menu do restauracji. Aktualizacje przyrostowe: wyślij nowy element menu wraz z elementem restauracji z polem |
Trwale usuń element najwyższego poziomu Dotyczy tylko typów |
Menu , Restaurant , Service |
Aktualizacje dodatkowe: wyślij wyraźne usunięcie. Pełne kanały: usuń element z pełnych kanałów przed następnym pobraniem przez Google elementu. W przeciwnym razie element zostanie ponownie dodany. |
Dodaj nowy obszar dostawy w określonym Service |
Service |
przyrostowe pliki danych: prześlij dany element Service ze wszystkimi polami w oryginalnej formie, tak jak w przypadku pełnych plików danych, ze nowym obszarem wyświetlania określonym w dokumencie areaServed z Service . |
Zaktualizuj szacowany czas dostawy w: Service |
Service |
Dodatkowe pliki danych: wyślij Service tak samo jak w plikach danych, chyba że jego hoursAvailable.deliveryHours jest odpowiednio zaktualizowany. |
Zaktualizuj ceny dostawy w: Service |
Service |
Dodatkowe pliki danych: wyślij pełne Service z zaktualizowanym offers.priceSpecification.price . |
Zaktualizuj godziny dostawy lub na wynos w: Service |
Service |
Dodatkowe pliki danych: wyślij Service tak samo jak w plikach danych, chyba że jego hoursAvailable jest odpowiednio zaktualizowany. |
Service (zmień minimalną kwotę zamówienia) |
Service |
przyrostowe pliki danych: wyślij pełne dane typu Service z aktualizacją Service.offers.priceSpecification.eligibleTransactionVolume . |
Usuń usługę MenuItem na stałe |
Menu |
Dodatkowe pliki danych: wyślij Menu tak samo jak w plikach danych, ale z atrybutem MenuItem usuń z listy hasMenuItems . |
Docelowy poziom czasu przetwarzania zadań wsadowych i przyrostowych aktualizacji
Encja dodana w ramach operacji zbiorczej lub aktualizacji przyrostowej zostanie przetworzona w ciągu 1–2 dni. Encja zaktualizowana lub usunięta zbiorczo zostanie przetworzona w ciągu 2 godzin. Nieaktualny element jest usuwany za 7 dni.
Możesz wysłać Google:
- Mieć wiele zadań wsadowych dziennie, aby zasoby były aktualne LUB
- Jedno zadanie wsadowe dziennie i przyrostowe interfejsy API, aby aktualizować zasoby reklamowe.