Questa sezione descrive come inviare a Google aggiornamenti delle entità dell'inventario sensibili al tempo. L'API Incremental Update consente di eseguire il push degli aggiornamenti ed eliminare le entità nell'inventario sandbox o di produzione quasi in tempo reale.
Questa funzionalità è destinata principalmente ad aggiornamenti che non puoi prevedere, come le chiusure di emergenza. Come regola, qualsiasi modifica inviata tramite l'API Incremental Update deve essere una modifica che deve essere pubblicata entro un massimo di un'ora. Se la modifica non deve essere applicata immediatamente, puoi utilizzare l'importazione in gruppo. Gli aggiornamenti incrementali vengono elaborati in non più di cinque minuti.
Prerequisiti
Prima di implementare gli aggiornamenti incrementali, è richiesto quanto segue:
- Viene creato un account di servizio con il ruolo di editor per il progetto Actions. Per maggiori dettagli, consulta Creare e configurare un progetto.
- I feed di dati di produzione o sandbox vengono ospitati e importati. Per maggiori dettagli, consulta Importazione in batch.
- (Facoltativo, ma consigliato) Installa la libreria client di Google nella lingua che preferisci per agevolare l'utilizzo di OAuth 2.0 durante la chiamata all'API. Gli esempi di codice inclusi di seguito utilizzano queste librerie. In caso contrario, dovrai gestire manualmente gli scambi di token, come descritto in Utilizzare OAuth 2.0 per accedere alle API di Google.
Endpoint
Nelle richieste riportate di seguito, sostituisci quanto segue:
- PROJECT_ID: ID progetto Google Cloud associato al progetto che hai creato in Creare e configurare un progetto.
- TYPE: il tipo di entità (proprietà
@type
) dell'oggetto nel feed di dati che desideri aggiornare. - ENTITY_ID (solo eliminazione endpoint): ID dell'entità da eliminare. Assicurati di applicare la codifica URL al tuo ID entità.
- DELETE_TIME (solo eliminazione endpoint): campo facoltativo per indicare l'ora in cui l'entità è stata eliminata nei sistemi (il valore predefinito è il momento in cui viene ricevuta la richiesta). Il valore dell'ora non deve essere nel futuro. Quando invii un'entità
tramite una chiamata incrementale, il controllo delle versioni dell'entità
utilizza il campo
delete_time
nel caso di una chiamata di eliminazione. Formatta questo valore comeyyyy-mm-ddTHH:mm:ssZ
Aggiorna endpoint
Per modificare un'entità, effettua una richiesta POST HTTP al seguente endpoint e includi un payload di aggiornamenti e aggiunte. Puoi aggiornare fino a 1000 entità in una singola chiamata API.
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities:batchPush
Ad esempio, se vuoi aggiornare le entità in un progetto con un ID "delivery-provider-id", l'endpoint sarà il seguente:
https://actions.googleapis.com/v2/apps/delivery-provider-id/entities:batchpush
Elimina endpoint
Per eliminare un'entità dal tuo inventario, effettua una richiesta HTTP DELETE al seguente endpoint.
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/TYPE/ENTITY_ID?entity.vertical=FOODORDERING&delete_time=DELETE_TIME
Ad esempio, per eliminare un'entità "MenuSezione" con ID "menuSezione_122" dal progetto "delivery-provider-id", devi effettuare una chiamata API HTTP DELETE a:
https://actions.googleapis.com/v2/apps/delivery-provider-id/entities/MenuSection/menuSection_122?entity.vertical=FOODORDERING
Ambiente sandbox
Per utilizzare l'API Incremental Update nel tuo inventario sandbox, segui le indicazioni riportate nella sezione Endpoint riportata sopra, ma invia richieste a /v2/sandbox/apps/
anziché a /v2/apps/
.
https://actions.googleapis.com/v2/sandbox/apps/PROJECT_ID/entities:batchPush
https://actions.googleapis.com/v2/sandbox/apps/PROJECT_ID/entities/TYPE/ENTITY_ID?entity.vertical=FOODORDERING&delete_time=DELETE_TIME
Aggiornare le entità
Ogni richiesta POST deve includere i parametri della richiesta insieme al payload JSON contenente i dati strutturati di qualsiasi tipo di entità elencato nello schema dell'inventario.
Aggiorna payload
Il formato JSON dovrebbe avere lo stesso aspetto del feed batch, con le seguenti differenze:
- Il corpo del payload non deve superare i 5 MB. Come per i feed batch, ti consigliamo di eliminare gli spazi vuoti per poter inserire più dati.
- La busta è la seguente:
{ "requests": [ { "entity": { "data":"ENTITY_DATA", "name": "apps/project_id>/entities/type/entity_id" }, "update_time":"UPDATE_TIMESTAMP" }, ], "vertical": "FOODORDERING" }
Nel payload riportato sopra, sostituisci quanto segue:
- ENTITY_DATA: entità in formato JSON serializzata come stringa. L'entità JSON-LD deve essere passata come stringa nel campo
data
. - UPDATE_TIMESTAMP (facoltativo): timestamp relativo all'aggiornamento dell'entità nei sistemi. Il valore dell'ora non deve essere nel futuro. Il timestamp predefinito si riferisce al momento in cui Google riceve la richiesta. Quando invii un'entità tramite una richiesta incrementale, il controllo delle versioni dell'entità utilizza anche il campo
update_time
nel caso di una richiesta di aggiunta/aggiornamento.
Esempi
Esempio 1: aggiornare un ristorante
Supponiamo che tu debba aggiornare con urgenza il numero di telefono di un ristorante. L'aggiornamento contiene il codice JSON per l'intero ristorante.
Prendi in considerazione un feed collettivo simile al seguente:
{ "@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 }
L'aggiornamento incrementale tramite HTTP POST sarebbe quindi il seguente:
POST v2/sandbox/apps/provider-project/entities:batchPush Host: actions.googleapis.com Content-Type: application/ld+json { "requests": [ { "entity": { "name": "apps/provider-project/entities/restaurant/restaurant12345", "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" }
Esempio 2: aggiornare più ristoranti
Per aggiornare due entità del ristorante in una singola chiamata API, la richiesta POST HTTP sarebbe la seguente:
POST v2/sandbox/apps/provider-project/entities:batchPush Host: actions.googleapis.com Content-Type: application/ld+json { "requests": [ { "entity": { "name": "apps/provider-project/entities/restaurant/restaurant12345", "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 } } }, { "entity": { "name": "apps/provider-project/entities/restaurant/restaurant123", "data": { "@type": "Restaurant", "@id": "restaurant123", "name": "Some Other Restaurant", "url": "https://www.provider.com/somerestaurant", "telephone": "+16501231235", "streetAddress": "385 Spear St", "addressLocality": "San Mateo", "addressRegion": "CA", "postalCode": "94115", "addressCountry": "US" } } } ] "vertical": "FOODORDERING" }
Esempio 3: aggiornare il prezzo di un elemento del menu
Supponiamo che tu debba modificare il prezzo di un elemento del menu. Come nell'esempio 1, l'aggiornamento deve contenere il codice JSON per l'intera entità di primo livello (il menu) e il feed utilizza lo schema di inventario v1.
Prendi in considerazione un feed collettivo simile al seguente:
{ "@type": "MenuItemOffer", "@id": "menuitemoffer6680262", "sku": "offer-cola", "menuItemId": "menuitem896532", "price": 3.00, "priceCurrency": "USD" }
L'aggiornamento incrementale tramite POST sarebbe il seguente:
POST v2/sandbox/apps/provider-project/entities:batchPush Host: actions.googleapis.com Content-Type: application/ld+json { "requests": [ { "entity": { "name": "apps/provider-project/entities/menuitemoffer/menuitemoffer6680262", "data": { "@type": "MenuItemOffer", "@id": "menuitemoffer6680262", "sku": "offer-cola", "menuItemId": "menuitem896532", "price": 1.00, "priceCurrency": "USD" }, "vertical": "FOODORDERING" } } ] "vertical": "FOODORDERING" }
Aggiunta di un'entità
Per aggiungere entità, evita di utilizzare gli aggiornamenti dell'inventario. Utilizza invece la procedura dei feed batch come descritto per lo schema dell'inventario v2.
Rimuovere un'entità
Per rimuovere le entità di primo livello, utilizza un endpoint leggermente modificato e nella richiesta utilizzi HTTP DELETE anziché HTTP POST.
Eliminazione di un'entità di primo livello
Prendi in considerazione la situazione in cui vuoi eliminare un ristorante in un feed. Devi anche eliminare i relativi servizi e menu.
Un endpoint di esempio per un'entità menu con ID "provider/ristorante/menu/nr":
DELETE v2/apps/delivery-provider-id/entities/menu/provider%2Frestaurant%2Fmenu%2Fnr?entity.vertical=FOODORDERING
Host: actions.googleapis.com
Un endpoint di esempio per un'entità ristorante con ID "https://www.provider.com/ristorante/nr":
DELETE v2/apps/delivery-provider-id/entities/restaurant/provider%2Frestaurant%2Fnr?entity.vertical=FOODORDERING
Host: actions.googleapis.com
Un endpoint di esempio per un'entità di servizio con ID "https://www.provider.com/ristorante/service/nr":
DELETE v2/apps/delivery-provider-id/entities/service/provider%2Frestaurant%2Fservice%2Fnr?entity.vertical=FOODORDERING
Host: actions.googleapis.com
}
Rimozione di entità secondarie
Non utilizzare HTTP DELETE per rimuovere una sottoentità all'interno di un'entità di primo livello, come una voce di menu all'interno di un menu. Considera invece la rimozione delle entità secondarie come un aggiornamento di un'entità di primo livello in cui l'entità secondaria viene rimossa dall'elenco pertinente o da reverseReference.
Codici di risposta API
Una chiamata riuscita non significa che il feed sia valido o corretto, ma solo che è stata effettuata la chiamata API. Le chiamate riuscite ricevono un codice di risposta HTTP 200, insieme a un corpo della risposta vuoto:
{}
In caso di errori, il codice di risposta HTTP non sarà 200 e il corpo della risposta indica l'errore.
Ad esempio, se l'utente ha impostato il valore "verticale" nella busta su FAKE_VERTICAL
, verrà visualizzato il messaggio seguente:
{
"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\""
}
]
}
]
}
}
Esempio di codice
Di seguito sono riportati alcuni esempi di come utilizzare l'API Incremental Update in diverse lingue. Questi esempi utilizzano le librerie di autenticazione di Google e presuppongono un feed che utilizza lo schema dell'inventario v1. Per soluzioni alternative, consulta l'articolo sull'utilizzo di OAuth 2.0 per applicazioni da server a server.
Aggiornare le entità
Node.js
Questo codice utilizza la libreria di autenticazione di Google per 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 = 'your/entity/id' const PROJECT_ID = 'type/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(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:batchPush`, body: { requests: [ { entity: { data: JSON.stringify(entity) name: `apps/${PROJECT_ID}/entities/${ENTITY_ID}` } } ], vertical: 'FOODORDERING' }, json: true }, (err, res, body) => { if (err) { return console.log(err); } console.log(`Response: ${JSON.stringify(res)}`) }) } updateEntity(entity)
Python
Questo codice utilizza la libreria di autenticazione di Google per Python.
from google.oauth2 import service_account from google.auth.transport.requests import AuthorizedSession import json import urllib PROJECT_ID = 'your-project-id' ENTITY_ID = 'type/your/entity/id' ENDPOINT = 'https://actions.googleapis.com/v2/apps/%s/entities:batchPush' % ( PROJECT_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() entity = {} entity['data'] = data #entity JSON-LD serialized as string entity['name'] = 'apps/%s/entities/%s' % (PROJECT_ID, urllib.quote(ENTITY_ID, '') ) # Populating the request request = {} request['entity'] = entity requestArray = [request] # Populating the payload payload = {} payload['requests'] = requestArray payload['vertical'] = 'FOODORDERING' response = authed_session.post(ENDPOINT, json=payload) print(response.text) #if successful, will be '{}'
Java
Questo codice utilizza la libreria di autenticazione di Google per Java.
private static final String PROJECT_ID = "your-project-id"; private static final String ENTITY_ID = "type/your-entity-id"; /** * 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 data) { String authToken = getAuthToken(); String endpoint = String.format("https://actions.googleapis.com/v2/apps/%s/entities/:batchPush", PROJECT_ID); JSONObject entity = new JSONObject(); entity.put("data", data.toString()); entity.put("name", String.format("apps/%s/entities/%s", PROJECT_ID, URLEncoder.encode(ENTITY_ID, "UTF-8"))); JSONObject request = new JSONObject(); request.put("entity", entity); JSONArray requestArray = new JSONArray(); requestArray.put(request); JSONObject payload = new JSONObject(); payload.put("requests", requestArray); payload.put("vertical", FOODORDERING); // Execute POST request executePostRequest(endpoint, authToken, payload); }
Rimuovere entità
Node.js
Questo codice utilizza la libreria di autenticazione di Google per 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
Questo codice utilizza la libreria di autenticazione di Google per Python.
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
Questo codice utilizza la libreria di autenticazione di Google per Java.
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)); }
Casi d'uso
I seguenti casi d'uso sono esempi di aggiornamenti incrementali, aggiornamenti completi dei feed e contenuti ad alto livello nella chiamata API:
Scenario | Entità da aggiornare | Descrizione ed effetti |
---|---|---|
Disattivazione di un servizio | Service |
Devi disattivare un servizio per un motivo imprevisto. Aggiornamenti incrementali: aggiorna l'entità Feed completi: assicurati di aggiornare l'entità dai feed completi
in modo che il valore |
Un articolo specifico non è disponibile | MenuItemOffer |
Aggiornamenti incrementali: invia l'entità MenuItemOffer
incapsulante con inventoryLevel impostato su 0 per il valore
MenuItem specificato e tutti gli altri dati invariati. |
Variazione di prezzo dell'elemento del menu | MenuItemOffer |
Aggiornamenti incrementali: invia l'entità MenuItemOffer
incapsulante con price impostato sul prezzo aggiornato per il valore
MenuItem specificato e tutti gli altri dati invariati. |
Aggiungi nuova entità di primo livello Applicabile solo per le entità di tipo |
Menu , Restaurant e Service |
Ad esempio, devi aggiungere un nuovo menù a un ristorante. Feed completi: aggiungi l'entità nei feed di dati e attendi l'importazione in gruppo. |
Elimina definitivamente l'entità di primo livello Applicabile solo per le entità di tipo |
Menu , Restaurant e Service |
Aggiornamenti incrementali: invia un'eliminazione esplicita. Feed completi: assicurati di rimuovere l'entità dai feed completi prima del successivo recupero da parte di Google, altrimenti l'entità verrà nuovamente aggiunta. |
Aggiungi una nuova area di consegna in una località Service specifica |
ServiceArea |
Feed incrementali: invia l'entità ServiceArea in questione con tutti i campi invariati, come faresti normalmente nei feed completi, con la nuova area di consegna specificata all'interno di polygon , geoRadius o postalCode . |
Aggiorna l'orario di arrivo previsto per la consegna a Service |
ServiceHours |
Feed incrementali: invia lo ServiceHours come nei
feed, tranne per il fatto che leadTimeMin viene aggiornato
di conseguenza. |
Aggiorna i prezzi di consegna in Service |
Fee |
Feed incrementali: invia la pubblicazione completa Fee con
price aggiornato. |
Aggiorna gli orari di consegna o asporto in Service |
ServiceHours |
Feed incrementali: invia lo ServiceHours come nei
feed, tranne per il fatto che le relative proprietà opens e closes vengono aggiornate
di conseguenza. |
Service (modifica dell'importo minimo dell'ordine) |
Fee |
Feed incrementali: invia Fee completo con
minPrice
aggiornato |
Elimina definitivamente un MenuItem |
Menu |
Feed incrementali: invia lo MenuItem come nei feed, ma con parentMenuSectionId vuoto.
|
SLO sul tempo di elaborazione per job batch e aggiornamenti incrementali
Un'entità aggiornata o eliminata tramite un batch viene elaborata entro due ore nella modalità migliore, mentre un'entità aggiornata tramite un aggiornamento incrementale viene elaborata entro cinque minuti. Un'entità inattiva viene eliminata dopo 7 giorni.
Puoi inviare a Google:
- Più job batch al giorno per mantenere aggiornato l'inventario OPPURE
- Un job batch al giorno e API incrementali per mantenere aggiornato l'inventario.