Esta seção descreve como você pode enviar atualizações urgentes dos seus feeds para Google. Com a API Incremental Updates, é possível atualizar e excluir entidades feeds quase em tempo real.
Essa funcionalidade se destina principalmente a atualizações que você não pode prever, como fechamentos de emergência. Como regra geral, qualquer alteração enviada por meio do A API Incremental Updates precisa ser uma mudança que precisa ser ativada em até uma semana. Se sua alteração não precisar ser refletida imediatamente, você poderá usar uma atualização em lote. As atualizações incrementais são processadas em no máximo cinco minutos.
Configuração
Para implementar atualizações incrementais, faça o seguinte:
- Siga as etapas descritas em Criar e configurar um projeto para: criar um projeto.
- Siga as etapas descritas em Configurar uma conta de serviço para criar uma conta de serviço. Você precisa ser um "Proprietário" da projeto para adicionar um "Editor" para a conta de serviço
- (Opcional, mas recomendado) Instale a biblioteca de cliente do Google na linguagem de sua escolha para facilitar o uso do OAuth 2.0 ao chamar o API. Os exemplos de código abaixo usam essas bibliotecas. Caso contrário, precisa lidar com trocas de token manualmente, conforme descrito em Como usar o OAuth 2.0 para acessar as APIs do Google.
Endpoint
Para notificar o Google sobre uma atualização, faça uma solicitação POST HTTP ao servidor Updates e incluem um payload de atualizações e inclusões. O esquema de inventário usado determina para qual endpoint fazer a solicitação:
Inventário v2
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/TYPE/ENTITY_ID:push
Inventário v1
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/ENTITY_ID:push
Para remover uma entidade, faça uma solicitação HTTP DELETE para o seguinte endpoint que corresponde ao esquema de inventário que você usa:
Inventário v2
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/TYPE/ENTITY_ID?entity.vertical=FOODORDERING&delete_time=DELETE_TIME
Inventário v1
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/ENTITY_ID?entity.vertical=FOODORDERING&delete_time=DELETE_TIME
Nas solicitações acima, substitua o seguinte:
- PROJECT_ID: ID do projeto do Google Cloud associado ao projeto que você criado em Criar e configurar um projeto.
- TYPE (somente esquema de inventário v2): o tipo de entidade (propriedade
@type
) do objeto no feed de dados que você deseja atualizar. - ENTITY_ID: ID da entidade incluída no payload. Não se esqueça de URL codifica o ID da entidade.
- DELETE_TIME (excluir apenas o endpoint): campo opcional para indicar o
hora em que a entidade foi excluída nos seus sistemas (o padrão é quando a solicitação é
recebidas). O valor de tempo não pode estar no futuro. Ao enviar uma entidade
com uma chamada incremental de controle de versão de entidade
também usa o campo
delete_time
no caso de uma chamada de exclusão. Formate isto valor comoyyyy-mm-ddTHH:mm:ssZ
Por exemplo, você tem um projeto com o ID "delivery-provider-id" que usa o esquema de inventário v2. Você deseja fazer alterações no restaurante com uma tipo de entidade "restaurante" de "MenuSection" e um ID de entidade "menuSection_122". O endpoint para atualizações dos dados seria o seguinte:
https://actions.googleapis.com/v2/apps/delivery-provider-id/entities/MenuSection/menuSection_122:push
Para remover essa mesma entidade, faça esta chamada de API DELETE HTTP:
https://actions.googleapis.com/v2/apps/delivery-provider-id/entities/MenuSection/menuSection_122?entity.vertical=FOODORDERING
Solicitações de sandbox
Para solicitações de sandbox, siga as orientações em Endpoint acima, mas
fazer solicitações para /v2/sandbox/apps/
em vez de para /v2/apps/
. Por exemplo, um
A solicitação de exclusão do sandbox para o esquema de inventário v2 é estruturada da seguinte maneira:
https://actions.googleapis.com/v2/sandbox/apps/PROJECT_ID/entities/TYPE/ENTITY_ID?entity.vertical=FOODORDERING&delete_time=DELETE_TIME
Atualizações e adições
Seus feeds em lote diários também devem conter as alterações enviadas por esta API. Caso contrário, as atualizações em lote vão substituir as alterações incrementais.
Payload
Cada solicitação POST deve incluir os parâmetros de solicitação junto com o JSON que contém os dados estruturados de qualquer tipo de entidade listado no esquema de inventário.
O JSON deve aparecer da mesma forma que no feed em lote, com o as seguintes diferenças:
- O corpo do payload não pode exceder 5 MB. Da mesma forma que o batch feeds, sugerimos que você elimine os espaços em branco para ajustar mais dados.
- O envelope é o seguinte:
{ "entity": { "data":"ENTITY_DATA", "vertical":"FOODORDERING" }, "update_time":"UPDATE_TIMESTAMP" }
No payload acima, substitua o seguinte:
- ENTITY_DATA: entidade no formato JSON serializada como uma string. A
A entidade JSON-LD precisa ser transmitida como uma string no campo
data
. - UPDATE_TIMESTAMP (opcional): carimbo de data/hora de quando a entidade foi atualizada em
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 um método
solicitação, o controle de versão da entidade também usa a
update_time
no caso de uma solicitação de adição/atualização.
Atualizar uma entidade
Exemplo 1: atualizar um restaurante
Suponha que você precise atualizar o número de telefone de um restaurante com urgência. Seu "update" contém o JSON de todo o restaurante.
Considere um feed em lote como 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 HTTP POST seria assim:
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" } }
Exemplo 2: 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, atualização deve conter o JSON para toda a entidade de nível superior (o menu) e os usa o esquema de inventário v1.
Considere um feed em lote como este:
{ "@type": "MenuItemOffer", "@id": "menuitemoffer6680262", "sku": "offer-cola", "menuItemId": "menuitem896532", "price": 3.00, "priceCurrency": "USD" }
A atualização incremental via POST seria assim:
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" } }
Como adicionar uma entidade
Para adicionar entidades, evite usar atualizações de inventário. Em vez disso, use os feeds em lote conforme descrito para o esquema de inventário v2.
Como remover uma entidade
Para remover entidades de nível superior, use um endpoint ligeiramente modificado, e usar HTTP DELETE em vez de HTTP POST na solicitação.
Não use HTTP DELETE para remover uma subentidade dentro de uma entidade de nível superior, como um item de menu dentro de um menu. Em vez disso, trate a remoção de subentidades como uma para uma entidade de nível superior na qual a subentidade é removida da lista ou parâmetro relevante.
Exemplo 1: exclusão de uma entidade de nível superior
Considere uma situação em que você deseja excluir um restaurante em um feed que usa o esquema de inventário v1. Você também precisa excluir os serviços e menus dela.
Um endpoint de exemplo para uma entidade de menu com ID "https://www.provider.com/restaurant/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
Um endpoint de exemplo para uma entidade de restaurante com ID "https://www.provider.com/restaurant/nr":
DELETE v2/apps/delivery-provider-id/entities/https%3A%2F%2Fwww.provider.com%2Frestaurant%2Fnr?entity.vertical=FOODORDERING
Host: actions.googleapis.com
Um endpoint de amostra para uma entidade de serviço com ID "https://www.provider.com/restaurant/service/nr":
DELETE v2/apps/delivery-provider-id/entities/https%3A%2F%2Fwww.provider.com%2Frestaurant%2Fservice%2Fnr?entity.vertical=FOODORDERING
Host: actions.googleapis.com
}
Exemplo 2: remover subentidades
Para remover uma subentidade de uma entidade de nível superior, envie a subentidade entidade com a subentidade removida do campo correspondente. O seguinte exemplo pressupõe que o feed usa o esquema de inventário v1.
Por exemplo, para remover uma área de cobertura, atualize o serviço com a área de cobertura
removido da lista de 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"
}
}
Códigos de resposta da API
Uma chamada bem-sucedida não significa que o feed é válido ou correto, apenas que o A chamada de API foi feita. Chamadas bem-sucedidas recebem um código de resposta HTTP 200, junto com um corpo de resposta vazio:
{}
No caso de falhas, o código de resposta HTTP não será 200, e o corpo da resposta indica o que deu errado.
Por exemplo, se o usuário definiu o campo "vertical" valor no envelope para
FAKE_VERTICAL
, você receberia esta mensagem:
{
"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 Updates em várias idiomas. Esses exemplos usam as bibliotecas do Google Auth e presumem que um feed usa 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 = '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
Este 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 = '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
Este 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 = "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); }
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
Este 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
Este 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 alto nível na chamada de API:
Cenário | Entidade de nível superior | Descrição e efeitos |
---|---|---|
Desativar um serviço | DisabledService |
Você precisar desativar um serviço por um motivo imprevisto. Atualizações incrementais:envie a entidade Feeds completos:atualize a entidade dos feeds completos
definir |
O item específico está esgotado | Menu |
Atualizações incrementais:envie o Menu de encapsulamento.
entidade com offer.inventoryLevel definido como 0 para o dado
MenuItem e todos os outros dados inalterados. |
Mudança no preço do item de menu | Menu |
Atualizações incrementais:envie o Menu de encapsulamento.
entidade com offer.price definido como o preço atualizado do
MenuItem e todos os outros dados inalterados. |
Adicionar nova entidade de nível superior Aplicável apenas para a entidade dos tipos |
Menu , Restaurant , Service |
Por exemplo, você precisa adicionar um novo cardápio a um restaurante. Atualizações incrementais:envie a nova entidade do cardápio com o restaurante.
com o campo |
Excluir entidade de nível superior permanentemente Aplicável apenas para a entidade dos tipos |
Menu , Restaurant , Service |
Atualizações incrementais:envie uma exclusão explícita. Feeds completos: remova a entidade dos feeds completos antes a próxima busca feita pelo Google. Caso contrário, a entidade será adicionada novamente. |
Adicionar uma nova área de entrega em uma Service específica |
Service |
Feeds incrementais:envie a entidade Service em questão com todos os seus
campos intactos, como faria normalmente nos feeds completos, com nova área de entrega
especificado em areaServed do Service . |
Atualize o horário previsto de chegada para Service |
Service |
Feeds incrementais:envie o Service igual ao
nos feeds, exceto que hoursAvailable.deliveryHours é atualizado
de maneira adequada. |
Atualize os preços de entrega para Service |
Service |
Feeds incrementais:envie Service completo com
offers.priceSpecification.price atualizado. |
Atualize os horários de entrega ou retirada em Service |
Service |
Feeds incrementais:envie o Service igual ao
nos feeds, exceto que hoursAvailable é atualizado
de maneira adequada. |
Service (alterar o valor mínimo do pedido) |
Service |
Feeds incrementais:envie Service completo com
Service.offers.priceSpecification.eligibleTransactionVolume
atualizado |
Excluir MenuItem permanentemente |
Menu |
Feeds incrementais: envie o Menu da mesma forma que no
feeds, mas com este MenuItem removido da
Lista hasMenuItems . |
SLO no tempo de processamento de jobs em lote e atualizações incrementais
Uma entidade adicionada por meio de atualização em lote ou incremental será processada em 1 a 2 dias. Uma entidade atualizada ou excluída em um lote será processada em 2 horas, enquanto uma entidade atualizada por meio de atualização incremental será processada em 5 minutos. Uma entidade desatualizada é excluída em 7 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.