Questa sezione descrive il modo in cui puoi inviare aggiornamenti urgenti per le entità del tuo inventario a Google. L'API Incremental Update consente di eseguire il push di aggiornamenti ed eliminare entità nell'inventario Sandbox o di produzione quasi in tempo reale.
Questa funzionalità è principalmente pensata per gli aggiornamenti che non puoi prevedere, ad esempio le chiusure di emergenza. Di norma, qualsiasi modifica inviata tramite l'API Incremental Update dovrebbe essere una modifica che deve essere pubblicata entro più di un'ora. Se la modifica non deve essere necessariamente immediata, puoi utilizzare l'importazione in batch. Gli aggiornamenti incrementali vengono elaborati in massimo cinque minuti.
Prerequisiti
I seguenti elementi sono obbligatori prima di implementare gli aggiornamenti incrementali:
- Un account di servizio viene creato con il ruolo di editor nel 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 la pagina relativa all'importazione in batch.
- (Facoltativo, ma consigliato) Installa la libreria client di Google nella lingua che preferisci per semplificare l'utilizzo di OAuth 2.0 quando chiami l'API. Le librerie di esempio incluse di seguito utilizzano queste librerie. In caso contrario, dovrai gestire manualmente gli scambi di token come descritto in Utilizzo di OAuth 2.0 per accedere alle API di Google.
Endpoint
Nelle richieste seguenti, sostituisci quanto segue:
- PROJECT_ID: ID progetto Google Cloud associato al progetto che hai creato nella sezione Creare e configurare un progetto.
- TYPE: il tipo di entità (proprietà
@type
) dell'oggetto nel feed di dati che vuoi aggiornare. - ENTITY_ID (solo endpoint di eliminazione): ID dell'entità da eliminare. Assicurati di codificare l'ID dell'URL.
- DELETE_TIME (solo eliminazione endpoint): campo facoltativo per indicare
l'ora in cui l'entità è stata eliminata sui sistemi (per impostazione predefinita viene ricevuta
la richiesta). Il valore dell'ora non deve essere futuro. Quando si invia un'entità tramite una chiamata incrementale, il controllo delle versioni delle entità utilizza anche il campo
delete_time
in caso di 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à nel 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à "MenuSection" con ID "menuSection_122" dal tuo progetto "delivery-provider-id""; dovrai effettuare una chiamata API HTTP DELETE per:
https://actions.googleapis.com/v2/apps/delivery-provider-id/entities/MenuSection/menuSection_122?entity.vertical=FOODORDERING
Ambiente sandbox
Per utilizzare l'API Incremental Update nell'inventario sandbox, segui le istruzioni negli endpoint precedenti, ma
fai 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
Aggiornamento delle 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 file JSON dovrebbe avere lo stesso aspetto del feed batch, con le seguenti differenze:
- Il corpo del payload non deve superare i 5 MB. Analogamente ai feed batch, ti suggeriamo di eliminare gli spazi vuoti per interessare 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 indicato sopra, sostituisci quanto segue:
- ENTITY_DATA: entità in formato JSON serializzata come stringa. L'entità JSON-LD deve essere passato come stringa nel campo
data
. - (Facoltativo) UPDATE_TIMESTAMP: timestamp quando è stata aggiornata l'entità nei sistemi. Il valore dell'ora non deve essere futuro. Il timestamp predefinito è il momento in cui
Google riceve la richiesta. Quando si invia un'entità tramite una richiesta incrementale, il controllo delle versioni delle entità utilizza anche il campo
update_time
nel caso di una richiesta di aggiunta/aggiornamento.
Esempi
Esempio 1: aggiornamento di un ristorante
Supponiamo che tu debba aggiornare urgentemente il numero di telefono di un ristorante, L'aggiornamento contiene JSON per l'intero ristorante.
Considera un feed batch 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 POST HTTP 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/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: aggiornamento di più ristoranti
Per aggiornare due entità ristorante in una singola chiamata API, la richiesta HTTP POST 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: aggiornamento del prezzo di una voce di menu
Supponi di dover modificare il prezzo di una voce del menu. Come nell'esempio 1, l'aggiornamento deve contenere il JSON per l'intera entità di primo livello (il menu) e il feed utilizza lo schema dell'inventario v1.
Considera un feed batch 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" }
Aggiungere un'entità
Per aggiungere entità, evita di utilizzare gli aggiornamenti dell'inventario. Utilizza invece la procedura dei feed batch come descritto per lo schema di inventario v2.
Rimozione di un'entità
Per rimuovere le entità di primo livello, devi utilizzare un endpoint leggermente modificato e utilizzare HTTP DELETE anziché HTTP POST nella richiesta.
Eliminazione di un'entità di primo livello
Prendi in considerazione una 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à di 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/servizio/nr":
DELETE v2/apps/delivery-provider-id/entities/service/provider%2Frestaurant%2Fservice%2Fnr?entity.vertical=FOODORDERING
Host: actions.googleapis.com
}
Rimozione dei sottotitoli
Non utilizzare HTTP DELETE per rimuovere un'entità secondaria all'interno di un'entità di primo livello, ad esempio una voce di menu all'interno di un menu. Considera, invece, la rimozione delle entità secondarie come un aggiornamento a un'entità di primo livello in cui la entità secondaria viene rimossa dall'elenco pertinente o da reversereference.
Codici di risposta API
Una chiamata riuscita non significa che il feed è valido o corretto, ma solo che la chiamata API è stata effettuata. Le chiamate riuscite ricevono un codice di risposta HTTP 200, insieme a un corpo di risposta vuoto:
{}
In caso di errori, il codice di risposta HTTP non è 200 e il corpo della risposta indica l'errore.
Ad esempio, se l'utente ha impostato il valore "vertical" sulla busta su FAKE_VERTICAL
, riceverai il seguente messaggio:
{
"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 varie lingue. Questi esempi utilizzano le librerie di autenticazione Google e presuppongono un feed utilizzando lo schema dell'inventario v1. Per soluzioni alternative, consulta Utilizzo di OAuth 2.0 per le applicazioni server-server.
Aggiornamento delle entità
Node.js
Questo codice utilizza la libreria di autenticazione 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 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 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); }
Rimozione delle entità
Node.js
Questo codice utilizza la libreria di autenticazione 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 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 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
Di seguito sono riportati alcuni esempi di aggiornamenti incrementali, aggiornamenti completi dei feed e contenuti nella chiamata API in generale:
Scenario | Entità da aggiornare | Descrizione ed effetti |
---|---|---|
Disabilitazione di un servizio | Service |
Devi disattivare un servizio per un motivo imprevisto. Aggiornamenti incrementali: aggiorna l'entità Feed completi: assicurati di aggiornare l'entità dal feed completo
impostando |
Un articolo specifico non è disponibile | MenuItemOffer |
Aggiornamenti incrementali: invia l'entità MenuItemOffer incapsulante con
inventoryLevel impostato su 0 per la data
MenuItem e tutti gli altri dati invariati. |
Variazione di prezzo della voce di menu | MenuItemOffer |
Aggiornamenti incrementali: invia l'entità MenuItemOffer incapsulante
con price impostato sul prezzo aggiornato per l'elemento
MenuItem e tutti gli altri dati invariati. |
Aggiungi nuova entità di primo livello Applicabile solo all'entità di tipo |
Menu , Restaurant e Service |
Ad esempio, devi aggiungere un nuovo menu a un ristorante. Feed completi: aggiungi l'entità nei feed di dati e attendi l'importazione in batch. |
Elimina l'entità di primo livello in modo permanente Applicabile solo all'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à riaggiunta. |
Aggiungi una nuova area di consegna in un determinato Service |
ServiceArea |
Feed incrementali: invia l'entità ServiceArea in questione con tutti i
campi invariati, come faresti normalmente all'interno dei feed completi, con la nuova area di consegna
specificata all'interno di polygon , geoRadius o postalCode . |
Aggiorna l'ora di arrivo stimata per la consegna in Service |
ServiceHours |
Feed incrementali: invia il valore ServiceHours allo stesso modo dei
feed, tranne per il fatto che il file leadTimeMin viene aggiornato
di conseguenza. |
Aggiorna i prezzi di consegna in Service |
Fee |
Feed incrementali: invia Fee di pubblicazione completa con price aggiornato. |
Aggiorna l'orario di consegna o ritiro in Service |
ServiceHours |
Feed incrementali: invia ServiceHours come nei
feed, tranne per il fatto che le relative proprietà opens e closes vengono aggiornate
di conseguenza. |
Service (importo minimo della modifica dell'ordine) |
Fee |
Feed incrementali: invia un Fee completo con minPrice aggiornato |
Elimina MenuItem in modo permanente |
Menu |
Feed incrementali: invia il valore MenuItem come nel feed, ma vuoto per parentMenuSectionId .
|
SLO sul tempo di elaborazione per i job batch e gli aggiornamenti incrementali
Un'entità aggiornata o eliminata tramite un batch verrà elaborata entro 2 ore nella migliore modalità possibile, mentre un'entità aggiornata tramite un aggiornamento incrementale verrà elaborata in 5 minuti. Un'entità inattiva viene eliminata entro 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.