Actualizaciones incrementales de inventario v2

En esta sección, se describe cómo puedes enviar actualizaciones urgentes de tu inventario. a Google. La API de Incremental Update te permite enviar actualizaciones y borrar de tu inventario de producción o de zona de pruebas casi en tiempo real.

Esta función está diseñada principalmente para actualizaciones que no puedes prever como cierres por emergencia. Como regla general, cualquier cambio que se envíe a través del La API de Incremental Update debe ser un cambio que debe publicarse en no más de una hora. Si no es necesario que el cambio se refleje de inmediato, puedes usar la transferencia por lotes. Las actualizaciones incrementales se procesan en no más de cinco minutos.

Requisitos previos

Se requieren los siguientes elementos para implementar las actualizaciones incrementales:

  1. Se crea una cuenta de servicio con el rol de editor para tu proyecto de Acciones. Para obtener más detalles, consulta Crea y configura un proyecto.
  2. Los feeds de datos de producción o de la zona de pruebas se alojan y transfieren. Para obtener más detalles, consulta Transferencia por lotes.
  3. (Opcional, pero recomendado) Instalar la biblioteca cliente de Google en el idioma que elijas para facilitar el uso de OAuth 2.0 cuando llames al en la API de Cloud. En las muestras de código que se incluyen a continuación, se usan estas bibliotecas. De lo contrario, debes manejar los intercambios de tokens de forma manual, tal como se describe en Cómo usar OAuth 2.0 para acceder a las APIs de Google.

Extremos

En las siguientes solicitudes, reemplaza lo siguiente:

  • PROJECT_ID: Es el ID del proyecto de Google Cloud asociado al proyecto que creado en Cómo crear y configurar un proyecto.
  • TYPE: Es el tipo de entidad (propiedad @type). del objeto del feed de datos que deseas actualizar.
  • ENTITY_ID (borrar solo el extremo): Es el ID de la entidad que se borrará. Asegúrate de Codifica el ID de la entidad como una URL.
  • DELETE_TIME (borrar solo el extremo): Es un campo opcional que denota el Hora en que se borró la entidad de tus sistemas (valor predeterminado es cuando la solicitud se recibidos). El valor del tiempo no debe ser posterior al actual. Cuando se envía una entidad a través de una llamada incremental, el control de versiones de entidades También usa el campo delete_time en el caso de una llamada a borrar. Asignar formato valor como yyyy-mm-ddTHH:mm:ssZ

Actualizar extremo

Para modificar una entidad, realiza una solicitud POST HTTP al siguiente extremo e incluye una carga útil de actualizaciones y adiciones. Puedes actualizar hasta 1,000 entidades con una sola llamada a la API.

https://actions.googleapis.com/v2/apps/PROJECT_ID/entities:batchPush

Por ejemplo, si quieres actualizar entidades en un proyecto con un ID “delivery-provider-id” el extremo sería el siguiente:

https://actions.googleapis.com/v2/apps/delivery-provider-id/entities:batchpush

Borrar extremo

Para borrar una entidad de tu inventario, realiza una solicitud HTTP DELETE al siguiente extremo.

https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/TYPE/ENTITY_ID?entity.vertical=FOODORDERING&delete_time=DELETE_TIME

Por ejemplo, para borrar una "MenuSection" entidad con el ID "menuSection_122" de su "delivery-provider-id" proyecto, realizarás una llamada a la API de HTTP DELETE para realizar lo siguiente:

https://actions.googleapis.com/v2/apps/delivery-provider-id/entities/MenuSection/menuSection_122?entity.vertical=FOODORDERING

Entorno de zona de pruebas

Para usar la API de actualización incremental en tu inventario de la zona de pruebas, sigue las instrucciones de Extremos anteriores, pero realiza solicitudes a /v2/sandbox/apps/ en lugar de 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

Actualiza entidades

Cada solicitud POST debe incluir los parámetros de la solicitud junto con el archivo JSON carga útil que contiene datos estructurados de cualquier tipo de entidad enumerado en la de inventario.

Actualizar carga útil

El archivo JSON debería aparecer igual que en el feed por lotes, con el las siguientes diferencias:

  • El cuerpo de la carga útil no debe superar los 5 MB de tamaño. De manera similar a lo que ocurre feeds, te sugerimos que quites los espacios en blanco para que quepan más datos.
  • El sobre es el siguiente:
{
  "requests": [
    {
      "entity": {
        "data":"ENTITY_DATA",
        "name": "apps/project_id>/entities/type/entity_id"
      },
      "update_time":"UPDATE_TIMESTAMP"
    },
  ],
  "vertical": "FOODORDERING"
}

En la carga útil anterior, reemplaza lo siguiente:

  • ENTITY_DATA: Entidad en formato JSON serializado como una cadena. El La entidad JSON-LD se debe pasar como una cadena en el campo data.
  • UPDATE_TIMESTAMP (opcional): Marca de tiempo del momento en que se actualizó la entidad en tus sistemas. El valor del tiempo no debe ser posterior al actual. La marca de tiempo predeterminada Google recibe la solicitud. Cuando se envía una entidad a través de un el control de versiones de la entidad también usa update_time en el caso de una solicitud de adición o actualización.

Ejemplos

Ejemplo 1: Actualiza un restaurante

Supongamos que necesitas actualizar el número de teléfono de un restaurante con urgencia. Tu la actualización contiene el JSON de todo el restaurante.

Considera un feed por lotes que se vea de la siguiente manera:

{
  "@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
}

Entonces, tu actualización incremental por HTTP POST sería la siguiente:

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"
}

Ejemplo 2: Actualiza varios restaurantes

Para actualizar dos entidades de restaurante en una sola llamada a la API, la solicitud HTTP POST sería la siguiente:

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"
}

Ejemplo 3: Actualiza el precio de un elemento de menú

Supongamos que necesitas cambiar el precio de un elemento del menú. Como en el ejemplo 1, tu update debe contener el JSON para toda la entidad de nivel superior (el menú), y el feed usa el esquema de inventario v1.

Considera un feed por lotes que se vea de la siguiente manera:

{
  "@type": "MenuItemOffer",
  "@id": "menuitemoffer6680262",
  "sku": "offer-cola",
  "menuItemId": "menuitem896532",
  "price": 3.00,
  "priceCurrency": "USD"
}

Entonces, la actualización incremental a través de POST sería la siguiente:

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"
}

Agrega una entidad

Para agregar entidades, evita usar actualizaciones de inventario. En su lugar, usa los feeds por lotes como se describe en el esquema de inventario v2.

Quita una entidad

Para quitar entidades de nivel superior, usa un extremo ligeramente modificado. y usar HTTP DELETE en lugar de HTTP POST en la solicitud.

Borra una entidad de nivel superior

Piensa en una situación en la que quieres borrar un restaurante de un feed. Debes borrar también sus servicios y menús.

Un extremo de muestra para una entidad de menú con ID "provider/restaurant/menu/nr":

DELETE v2/apps/delivery-provider-id/entities/menu/provider%2Frestaurant%2Fmenu%2Fnr?entity.vertical=FOODORDERING
Host: actions.googleapis.com

Un extremo de muestra para una entidad de restaurante con 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

Un extremo de muestra para una entidad de servicio con 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
}

Quitar subentidades

No uses HTTP DELETE para quitar una subentidad dentro de una entidad de nivel superior, como un elemento de menú dentro de un menú. En cambio, trata la eliminación de subentidades como un actualización a una entidad de nivel superior en la que la subentidad se quita del lista correspondiente o reverseReference.

Códigos de respuesta de la API

Una llamada exitosa no significa que el feed sea válido o correcto, sino que Se realizó una llamada a la API. Las llamadas correctas reciben el código 200 de respuesta HTTP, junto con un cuerpo de respuesta vacío:

{}

Para fallas, el código de respuesta HTTP no será 200, y el cuerpo de la respuesta indica qué salió mal.

Por ejemplo, si el usuario configuró la "vertical"; valor en el sobre para FAKE_VERTICAL, recibirás el siguiente mensaje:

{
  "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\""
          }
        ]
      }
    ]
  }
}

Muestra de código

Estos son algunos ejemplos de cómo usar la API de Incremental Update en varios idiomas. Estas muestras usan las bibliotecas de autenticación de Google y suponen que un feed usa el esquema de inventario v1. Para encontrar soluciones alternativas, consulta Uso de OAuth 2.0 para aplicaciones de servidor a servidor.

Actualiza entidades

Node.js

Este código usa la biblioteca auth de 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

Este código usa la biblioteca auth de 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

Este código usa la biblioteca auth de 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);
}

Cómo quitar entidades

Node.js

Este código usa la biblioteca auth de 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 la biblioteca auth de 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 la biblioteca auth de 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

Estos son ejemplos de actualizaciones incrementales, actualizaciones de feeds completas, y el contenido a un alto nivel en la llamada a la API:

Situación Entidad que se actualizará Descripción y efectos
Inhabilita un servicio Service

Debes inhabilitar un servicio por un motivo imprevisto.

Actualizaciones incrementales: Actualiza la entidad Service en estableciendo su propiedad isDisabled en true, pero mantienen las demás propiedades.

Feeds completos: Asegúrate de actualizar la entidad desde los feeds completos. para que isDisabled se establezca en true antes de la siguiente recuperación de Google. De lo contrario, se volverá a habilitar la entidad.

El artículo específico está agotado MenuItemOffer Actualizaciones incrementales: Envía el MenuItemOffer de encapsulamiento. con inventoryLevel establecido en 0 para el valor especificado MenuItem y todos los demás datos sin cambios.
Cambio de precio de un elemento de menú MenuItemOffer Actualizaciones incrementales: Envía el MenuItemOffer de encapsulamiento. entidad con price establecido en el precio actualizado del precio especificado MenuItem y todos los demás datos sin cambios.

Agregar nueva entidad de nivel superior

Solo se aplica a entidades de los tipos Menu, Restaurant y Service.

Menu, Restaurant, Service

Por ejemplo, si necesitas agregar un nuevo menú a un restaurante.

Feeds completos: Agrega la entidad a tus feeds de datos y espera la transferencia por lotes.

Borrar la entidad de nivel superior de forma permanente

Solo se aplica a entidades de los tipos Menu, Restaurant y Service.

Menu, Restaurant, Service

Actualizaciones incrementales: Envía un Eliminación explícita:

Feeds completos: Asegúrate de quitar la entidad de los feeds completos antes de la siguiente recuperación de Google. De lo contrario, se volverá a agregar la entidad.

Agrega una nueva área de entrega en una Service específica ServiceArea Feeds incrementales: Envía la entidad ServiceArea en cuestión con todos sus intactos, como lo harías normalmente en los feeds completos, con un área de entrega nueva se especifica dentro de polygon, geoRadius o postalCode.
Actualiza la hora estimada de entrega en Service ServiceHours Feeds incrementales: Envía el ServiceHours igual que en los feeds, excepto que se actualiza su leadTimeMin según corresponda.
Actualiza los precios de entrega en Service Fee Feeds incrementales: Envía la publicación completa Fee con Se actualizó price.
Actualiza los horarios de comida para llevar o entrega a domicilio en Service ServiceHours Feeds incrementales: Envía el ServiceHours igual que en los feeds, excepto que se actualizan sus propiedades opens y closes según corresponda.
Service (cambiar el importe mínimo del pedido) Fee Feeds incrementales: Envía el Fee completo con minPrice actualizado
Borrar un MenuItem de forma permanente Menu Feeds incrementales: Envía el MenuItem igual que en el feeds, pero con parentMenuSectionId vacío.

SLO en el tiempo de procesamiento para trabajos por lotes y actualizaciones incrementales

Una entidad actualizada o borrada a través de un lote se procesará en un plazo de 2 horas en el modo de mejor esfuerzo, mientras que una entidad actualizada a través de una actualización incremental se procesará en 5 minutos. Una entidad inactiva se borra dentro de 7 días.

Puedes enviarle a Google una de las siguientes opciones:

  • Múltiples trabajos por lotes por día para mantener tu inventario actualizado
  • Un trabajo por lotes al día y APIs incrementales para mantener tu inventario actualizado