Esta seção descreve como enviar atualizações urgentes das entidades de inventário ao Google. A API Incremental Update permite enviar atualizações e excluir entidades no seu sandbox ou inventário de produção quase em tempo real.
Essa funcionalidade é destinada principalmente a atualizações que você não pode prever, como fechamentos de emergência. Como regra, qualquer mudança enviada pela API Incremental Update precisa ser ativada em menos de uma hora. Se a mudança não precisar ser refletida imediatamente, use a transferência em lote. As atualizações incrementais são processadas em até cinco minutos.
Pré-requisitos
Os itens a seguir são necessários antes de implementar atualizações incrementais:
- Uma conta de serviço é criada com a função de editor no seu projeto do Actions. Para mais detalhes, consulte Criar e configurar um projeto.
- Os feeds de dados de produção ou sandbox são hospedados e ingeridos. Para mais detalhes, consulte Ingestão em lote.
- (Opcional, mas recomendado) Instale a Biblioteca de cliente do Google no idioma de sua escolha para facilitar o uso do OAuth 2.0 ao chamar a API. Os exemplos de código abaixo usam essas bibliotecas. Caso contrário, será necessário processar as trocas de token manualmente, conforme descrito em Como usar o OAuth 2.0 para acessar as APIs do Google.
Endpoints
Nas solicitações abaixo, substitua o seguinte:
- PROJECT_ID: o ID do projeto do Google Cloud associado ao projeto que você criou em Criar e configurar um projeto.
- TYPE: o tipo de entidade (propriedade
@type
) do objeto no seu feed de dados que você quer atualizar. - ENTITY_ID (somente endpoint de exclusão): ID da entidade a ser excluída. Codifique o ID da entidade em URL.
- DELETE_TIME (somente endpoint de exclusão): campo opcional para indicar o
momento em que a entidade foi excluída nos seus sistemas (o padrão é quando a solicitação é
recebida). O valor de tempo não pode estar no futuro. Ao enviar uma entidade
por uma chamada incremental, o controle de versões de entidade
também usa o campo
delete_time
no caso de uma chamada de exclusão. Formatar este valor comoyyyy-mm-ddTHH:mm:ssZ
Atualizar endpoint
Para modificar uma entidade, faça uma solicitação HTTP POST para o endpoint a seguir e inclua um payload de atualizações e adições. É possível fazer atualizações em até mil entidades em uma única chamada de API.
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities:batchPush
Por exemplo, se você quiser atualizar entidades em um projeto com um ID "delivery-provider-id", o endpoint será o seguinte:
https://actions.googleapis.com/v2/apps/delivery-provider-id/entities:batchpush
Excluir endpoint
Para excluir uma entidade do seu inventário, faça uma solicitação HTTP DELETE para o endpoint a seguir.
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/TYPE/ENTITY_ID?entity.vertical=FOODORDERING&delete_time=DELETE_TIME
Por exemplo, para excluir uma entidade "MenuSection" com o ID "menuSection_122" do projeto "delivery-provider-id", faça uma chamada de API HTTP DELETE para:
https://actions.googleapis.com/v2/apps/delivery-provider-id/entities/MenuSection/menuSection_122?entity.vertical=FOODORDERING
Ambiente de sandbox
Para usar a API Incremental Update no seu inventário de sandbox, siga as orientações nos Endpoints acima, mas
faça solicitações para /v2/sandbox/apps/
em vez de /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
Como atualizar entidades
Cada solicitação POST precisa incluir os parâmetros de solicitação com o payload JSON que contém os dados estruturados de qualquer tipo de entidade listado no esquema de inventário.
Atualizar payload
O JSON vai aparecer da mesma forma que no feed em lote, com as seguintes diferenças:
- O corpo do payload não pode exceder 5 MB. Assim como nos feeds em lote, sugerimos que você remova espaços em branco para ajustar mais dados.
- O envelope é o seguinte:
{ "requests": [ { "entity": { "data":"ENTITY_DATA", "name": "apps/project_id>/entities/type/entity_id" }, "update_time":"UPDATE_TIMESTAMP" }, ], "vertical": "FOODORDERING" }
No payload acima, substitua o seguinte:
- ENTITY_DATA: entidade no formato JSON serializada como uma string. A
entidade JSON-LD precisa ser transmitida como uma string no campo
data
. - UPDATE_TIMESTAMP (opcional): carimbo de data/hora em que a entidade foi atualizada nos
seus sistemas. O valor de tempo não pode estar no futuro. O carimbo de data/hora padrão é quando
o Google recebe a solicitação. Ao enviar uma entidade por uma solicitação incremental, o controle de versão da entidade também usa o campo
update_time
no caso de uma solicitação de adição/atualização.
Exemplos
Exemplo 1: atualizar um restaurante
Suponha que você precise atualizar com urgência o número de telefone de um restaurante. Sua atualização contém o JSON de todo o restaurante.
Considere um feed em lote parecido com este:
{ "@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 }
A atualização incremental por POST HTTP será a seguinte:
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" }
Exemplo 2: atualizar vários restaurantes
Para atualizar duas entidades de restaurante em uma única chamada de API, a solicitação HTTP POST será a seguinte:
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" }
Exemplo 3: atualizar o preço de um item de menu
Suponha que você precise mudar o preço de um item do menu. Como no Exemplo 1, a atualização precisa conter o JSON de toda a entidade de nível superior (o menu), e o feed usa o esquema de inventário v1.
Considere um feed em lote parecido com este:
{ "@type": "MenuItemOffer", "@id": "menuitemoffer6680262", "sku": "offer-cola", "menuItemId": "menuitem896532", "price": 3.00, "priceCurrency": "USD" }
A atualização incremental por POST será a seguinte:
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" }
Como adicionar uma entidade
Para adicionar entidades, evite usar atualizações de inventário. Em vez disso, use o processo de feeds em lote, conforme descrito para o esquema de inventário v2.
Como remover uma entidade
Para remover entidades de alto nível, use um endpoint ligeiramente modificado e use o HTTP DELETE em vez do HTTP POST na solicitação.
Como excluir uma entidade de nível superior
Considere uma situação em que você quer excluir um restaurante de um feed. Você também precisa excluir os serviços e menus.
Um endpoint de exemplo para uma entidade de menu com o ID "provider/restaurant/menu/nr":
DELETE v2/apps/delivery-provider-id/entities/menu/provider%2Frestaurant%2Fmenu%2Fnr?entity.vertical=FOODORDERING
Host: actions.googleapis.com
Um exemplo de endpoint para uma entidade de restaurante com o ID "https://www.provider.com/restaurant/nr":
DELETE v2/apps/delivery-provider-id/entities/restaurant/provider%2Frestaurant%2Fnr?entity.vertical=FOODORDERING
Host: actions.googleapis.com
Um endpoint de exemplo para uma entidade de serviço com o ID "https://www.provider.com/restaurant/service/nr":
DELETE v2/apps/delivery-provider-id/entities/service/provider%2Frestaurant%2Fservice%2Fnr?entity.vertical=FOODORDERING
Host: actions.googleapis.com
}
Como remover subentidades
Não use o HTTP DELETE para remover uma subentidade em uma entidade de nível superior, como um item de menu em um menu. Em vez disso, trate a remoção de subentidades como uma atualização de uma entidade de nível superior em que a subentidade é removida da lista relevante ou da reverseReference.
Códigos de resposta da API
Uma chamada bem-sucedida não significa que o feed é válido ou correto, apenas que a chamada de API foi feita. As chamadas bem-sucedidas recebem um código de resposta HTTP 200, além de um corpo de resposta vazio:
{}
Em caso de falhas, o código de resposta HTTP não será 200, e o corpo da resposta indicará o que deu errado.
Por exemplo, se o usuário tiver definido o valor "vertical" no envelope como
FAKE_VERTICAL
, você vai receber a mensagem abaixo:
{
"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\""
}
]
}
]
}
}
Exemplo de código
Confira abaixo alguns exemplos de como usar a API Incremental Update em várias línguas. Esses exemplos usam as bibliotecas Google Auth e assumem um feed usando o esquema de inventário v1. Para soluções alternativas, consulte Usar o OAuth 2.0 para aplicativos de servidor para servidor.
Como atualizar entidades
Node.js
Este código usa a biblioteca de autenticação do Google para 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
Esse código usa a biblioteca de autenticação do Google para 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
Esse código usa a biblioteca de autenticação do Google para 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); }
Como remover entidades
Node.js
Este código usa a biblioteca de autenticação do Google para 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
Esse código usa a biblioteca de autenticação do Google para 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
Esse código usa a biblioteca de autenticação do Google para 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)); }
Casos de uso
Os casos de uso a seguir são exemplos de atualizações incrementais, atualizações completas de feed e o conteúdo em um nível alto na chamada de API:
Cenário | Entidade a ser atualizada | Descrição e efeitos |
---|---|---|
Como desativar um serviço | Service |
Você precisa desativar um serviço por um motivo imprevisto. Atualizações incrementais:atualize a entidade Feeds completos:atualize a entidade dos feeds completos para que |
Um item específico está esgotado | MenuItemOffer |
Atualizações incrementais:envie a entidade MenuItemOffer
encapsulante com inventoryLevel definido como 0 para o
MenuItem fornecido e todos os outros dados inalterados. |
Mudança de preço do item do menu | MenuItemOffer |
Atualizações incrementais:envie a entidade MenuItemOffer
encapsulada com price definida como o preço atualizado para o
MenuItem fornecido e todos os outros dados inalterados. |
Adicionar nova entidade de nível superior Aplicável apenas a entidades dos tipos |
Menu , Restaurant , Service |
Por exemplo, você precisa adicionar um novo cardápio a um restaurante. Feeds completos:adicione a entidade nos feeds de dados e aguarde a transferência em lote. |
Excluir entidade de nível superior permanentemente Aplicável apenas a entidades dos tipos |
Menu , Restaurant , Service |
Atualizações incrementais:envie uma exclusão explícita. Feeds completos:remova a entidade dos feeds completos antes da próxima busca pelo Google. Caso contrário, ela será adicionada novamente. |
Adicionar uma nova área de entrega em um Service específico |
ServiceArea |
Feeds incrementais:envie a entidade ServiceArea em questão com todos os campos intactos, como você faria normalmente nos feeds completos, com a nova área de entrega especificada em polygon , geoRadius ou postalCode . |
Atualizar o horário estimado de chegada da entrega em Service |
ServiceHours |
Feeds incrementais:envie o ServiceHours igual aos
feeds, exceto que o leadTimeMin é atualizado
de acordo. |
Atualizar os preços de entrega em Service |
Fee |
Feeds incrementais:envie Fee de envio completo com
price atualizado. |
Atualizar o horário de entrega ou retirada em Service |
ServiceHours |
Feeds incrementais:envie o ServiceHours da mesma forma que nos feeds, exceto que as propriedades opens e closes são atualizadas. |
Service (mudar o valor mínimo do pedido) |
Fee |
Feeds incrementais:envie um Fee completo com o minPrice atualizado. |
Excluir um MenuItem permanentemente |
Menu |
Feeds incrementais:envie o MenuItem igual aos feeds, mas com o parentMenuSectionId vazio.
|
SLO no tempo de processamento para trabalhos em lote e atualizações incrementais
Uma entidade atualizada ou excluída em lote será processada em até duas horas no modo de melhor esforço, enquanto uma entidade atualizada por uma atualização incremental será processada em cinco minutos. Uma entidade desatualizada é excluída em sete dias.
Você pode enviar ao Google:
- Vários jobs em lote por dia para manter seu inventário atualizado OU
- Um job em lote por dia e APIs incrementais para manter seu inventário atualizado.