Mises à jour incrémentielles de l'inventaire (v2)

<ph type="x-smartling-placeholder">

Cette section explique comment envoyer des mises à jour urgentes de votre inventaire. à Google. L'API Progressive Update permet de déployer des mises à jour et de supprimer dans votre inventaire de bac à sable ou de production, quasiment en temps réel.

Cette fonctionnalité est principalement destinée aux mises à jour que vous ne pouvez pas prévoir, comme les routes fermées en urgence. En règle générale, toute modification soumise via le L'API de mise à jour incrémentielle doit être une modification qui ne doit pas être mise en ligne au plus tard une heure. Si votre modification n'a pas besoin d'être appliquée immédiatement, vous pouvez utiliser l'ingestion par lots. Les mises à jour incrémentielles sont traitées en cinq minutes maximum.

Prérequis

Les éléments suivants sont requis pour implémenter les mises à jour incrémentielles:

  1. Un compte de service est créé avec le rôle d'éditeur pour votre projet Actions. Pour en savoir plus, consultez Créez et configurez un projet.
  2. Les flux de données de production ou de bac à sable sont hébergés et ingérés. Pour en savoir plus, consultez Ingestion par lots.
  3. (Facultatif, mais recommandé) Installez la bibliothèque cliente Google. dans le langage de votre choix afin de faciliter l'utilisation d'OAuth 2.0 lors de l'appel de la méthode API. Les exemples de code inclus ci-dessous utilisent ces bibliothèques. Sinon, vous devez gérer manuellement les échanges de jetons, comme décrit dans la section Utiliser OAuth 2.0 pour accéder aux API Google.

Points de terminaison

Dans les requêtes ci-dessous, remplacez les éléments suivants:

  • PROJECT_ID: ID du projet Google Cloud associé au projet que vous dans la section Créer et configurer un projet.
  • TYPE: type d'entité (propriété @type) de l'objet de votre flux de données à mettre à jour.
  • ENTITY_ID (supprimer le point de terminaison uniquement): ID de l'entité à supprimer. Veillez à Encodez votre ID d'entité en URL.
  • DELETE_TIME (supprimer le point de terminaison uniquement): champ facultatif permettant d'indiquer l'heure à laquelle l'entité a été supprimée de vos systèmes (par défaut, lorsque la requête est reçu). La valeur de l'heure ne doit pas se situer dans le futur. Lors de l'envoi d'une entité via un appel incrémentiel, la gestion des versions d'entités utilise également le champ delete_time dans le cas d'un appel de suppression. Mettre en forme valeur yyyy-mm-ddTHH:mm:ssZ

Mettre à jour le point de terminaison

Pour modifier une entité, envoyez une requête HTTP POST au point de terminaison suivant et inclure une charge utile de mises à jour et ajouts. Vous pouvez mettre à jour jusqu'à 1 000 entités dans un seul appel d'API.

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

Par exemple, si vous souhaitez mettre à jour les entités d'un projet ayant l'ID "delivery-provider-id" le point de terminaison est le suivant:

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

Supprimer un point de terminaison

Pour supprimer une entité de votre inventaire, envoyez une requête HTTP DELETE au point de terminaison suivant.

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

Par exemple, pour supprimer une "MenuSection", entité associée à l'ID "menuSection_122" à partir de l'ID du fournisseur de livraison (delivery-provider-id) vous devez effectuer un appel d'API HTTP DELETE vers:

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

Environnement de bac à sable

Pour utiliser l'API de mise à jour incrémentielle dans votre inventaire de bac à sable, suivez les instructions de la section Points de terminaison ci-dessus, mais envoyer des requêtes à /v2/sandbox/apps/ au lieu 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

Mettre à jour des entités

Chaque requête POST doit inclure les paramètres de requête avec le fichier contenant les données structurées de tout type d'entité listé dans le d'inventaire.

Mettre à jour la charge utile

Le fichier JSON doit apparaître de la même manière que dans le flux par lot, avec le préfixe différences suivantes:

  • La taille du corps de la charge utile ne doit pas dépasser 5 Mo. Comme pour le traitement par lot nous vous conseillons de supprimer les espaces blancs afin d'insérer davantage de données.
  • L'enveloppe se présente comme suit:
{
  "requests": [
    {
      "entity": {
        "data":"ENTITY_DATA",
        "name": "apps/project_id>/entities/type/entity_id"
      },
      "update_time":"UPDATE_TIMESTAMP"
    },
  ],
  "vertical": "FOODORDERING"
}

Dans la charge utile ci-dessus, remplacez les éléments suivants:

  • ENTITY_DATA: entité au format JSON sérialisée en tant que chaîne. La L'entité JSON-LD doit être transmise sous forme de chaîne dans le champ data.
  • UPDATE_TIMESTAMP (facultatif): horodatage de la mise à jour de l'entité dans vos systèmes. La valeur de l'heure ne doit pas se situer dans le futur. Le code temporel par défaut est le moment Google reçoit la demande. Lors de l'envoi d'une entité via un la gestion des versions des entités utilise également update_time dans le cas d'une requête d'ajout/de mise à jour.

Exemples

Exemple 1: Mettre à jour un restaurant

Supposons que vous ayez besoin de mettre à jour en urgence le numéro de téléphone d'un restaurant. Votre contient le fichier JSON de tout le restaurant.

Prenons l'exemple d'un flux par lot qui se présente comme suit:

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

Votre mise à jour incrémentielle par HTTP POST se présenterait comme suit:

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

Exemple 2: Mettre à jour plusieurs restaurants

Pour mettre à jour deux entités de restaurant dans un seul appel d'API, la requête HTTP POST se présente comme suit:

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

Exemple 3: Mettre à jour le prix d'un élément de menu

Supposons que vous deviez modifier le prix d'un élément de menu. Comme dans l'exemple 1, doit contenir le fichier JSON de l'ensemble de l'entité de premier niveau (le menu) ; utilise le schéma d'inventaire v1.

Prenons l'exemple d'un flux par lot qui se présente comme suit:

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

Votre mise à jour incrémentielle via la méthode POST se présenterait comme suit:

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

Ajouter une entité

Pour ajouter des entités, évitez d'utiliser des mises à jour d'inventaire. Utilisez plutôt les flux par lot comme décrit pour le schéma d'inventaire v2.

Supprimer une entité

Pour supprimer des entités de niveau supérieur, utilisez un point de terminaison légèrement modifié, et utiliser HTTP DELETE au lieu de HTTP POST dans la requête.

Suppression d'une entité de niveau supérieur

Imaginons que vous souhaitiez supprimer un restaurant d'un flux. Vous devez supprimera également ses services et ses menus.

Exemple de point de terminaison pour une entité de menu ayant un ID &quot;provider/restaurant/menu/nr&quot;:

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

Exemple de point de terminaison pour une entité de restaurant ayant un ID &quot;https://www.provider.com/restaurant/nr&quot;:

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

Exemple de point de terminaison pour une entité de service avec ID &quot;https://www.provider.com/restaurant/service/nr&quot;:

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

Supprimer des sous-entités

N'utilisez pas HTTP DELETE pour supprimer une sous-entité au sein d'une entité de niveau supérieur, telle que un élément de menu dans un menu. Considérez plutôt la suppression de sous-entités comme une une mise à jour d'une entité de niveau supérieur dans laquelle la sous-entité est supprimée de la liste pertinente ou reverseReference.

Codes de réponse de l'API

Un appel réussi ne signifie pas que le flux est valide ou correct, mais uniquement que le L'appel d'API a été effectué. Les appels réussis reçoivent un code de réponse HTTP 200, ainsi que avec un corps de réponse vide:

{}

En cas d'échec, le code de réponse HTTP n'est pas 200 et le corps de la réponse indique ce qui s'est mal passé.

Par exemple, si l'utilisateur a défini le "vertical" de l'enveloppe à FAKE_VERTICAL, vous devriez recevoir le message ci-dessous:

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

Exemple de code

Vous trouverez ci-dessous quelques exemples d'utilisation de l'API incrémentiel de mise à jour dans différents langues. Ces exemples utilisent les bibliothèques Google Auth et supposent qu'un flux utilise du schéma d'inventaire v1. Pour d'autres solutions, reportez-vous à Utiliser OAuth 2.0 pour l'authentification serveur à serveur

Mettre à jour des entités

Node.js

Ce code utilise la bibliothèque d'authentification Google pour 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

Ce code utilise la bibliothèque d'authentification Google pour 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

Ce code utilise la bibliothèque d'authentification Google pour 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);
}

Supprimer des entités

Node.js

Ce code utilise la bibliothèque d'authentification Google pour 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

Ce code utilise la bibliothèque d'authentification Google pour 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

Ce code utilise la bibliothèque d'authentification Google pour 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));
}

Cas d'utilisation

Voici des exemples de mises à jour incrémentielles, de mises à jour de flux complètes, et le contenu à un niveau élevé dans l'appel d'API:

Scénario Entité à mettre à jour Description et effets
Désactiver un service Service

Vous devez désactiver un service pour une raison imprévue.

Mises à jour incrémentielles:mettez à jour l'entité Service dans en définissant sa propriété isDisabled sur true, tout en conservant les mêmes propriétés.

Flux complets:veillez à mettre à jour l'entité à partir des flux complets. de définir isDisabled sur true avant lors de la prochaine extraction par Google, sinon l'entité sera réactivée.

Un article spécifique n'est pas disponible MenuItemOffer Mises à jour incrémentielles:envoyez le MenuItemOffer d'encapsulation. entité avec inventoryLevel défini sur 0 pour l'entité MenuItem et toutes les autres données inchangées.
Changement de prix de l'élément de menu MenuItemOffer Mises à jour incrémentielles:envoyez le MenuItemOffer d'encapsulation. entité avec price défini sur le nouveau prix pour l'entité donnée MenuItem et toutes les autres données inchangées.

Ajouter une entité de niveau supérieur

S'applique uniquement aux entités de type Menu, Restaurant et Service.

Menu, Restaurant, Service

Par exemple, vous devez ajouter un nouveau menu à un restaurant.

Flux complets:ajoutez l'entité à vos flux de données et attendez l'ingestion par lots.

Supprimer définitivement l'entité de premier niveau

S'applique uniquement aux entités de type Menu, Restaurant et Service.

Menu, Restaurant, Service

Mises à jour incrémentielles:envoyez un suppression explicite.

Flux complets:veillez à supprimer l'entité des flux complets avant lors de la prochaine extraction par Google, sinon l'entité sera de nouveau ajoutée.

Ajouter une zone de livraison dans un Service spécifique ServiceArea Flux partiels:envoyez l'entité ServiceArea en question avec tous ses les champs restent intacts, comme vous le feriez dans les flux complets, avec une nouvelle zone de livraison spécifié dans polygon, geoRadius ou postalCode.
Modifier l'heure d'arrivée estimée pour la livraison à Service ServiceHours Flux partiels:envoyez l'ServiceHours de la même manière que dans les flux, sauf que son leadTimeMin est mis à jour en conséquence.
Modifier les prix de livraison dans le pays suivant : Service Fee Flux partiels:envoyer la version complète Fee avec price mis à jour.
Modifier les horaires de livraison ou de vente à emporter dans Service ServiceHours Flux partiels:envoyez l'ServiceHours de la même manière que dans les flux, sauf que ses propriétés opens et closes sont mises à jour en conséquence.
Service (modifier le montant minimal de commande) Fee Flux partiels:envoyer la version complète de Fee avec minPrice mis à jour
Supprimer définitivement un(e) MenuItem Menu Flux partiels:envoyez l'MenuItem de la même manière que dans les flux, mais avec parentMenuSectionId vide.

SLO sur le temps de traitement des jobs par lot et des mises à jour incrémentielles

Une entité mise à jour ou supprimée par lot est traitée sous 2 heures, alors qu'une entité mise à jour par incréments est traitée en 5 minutes. Une entité obsolète est supprimée au bout de sept jours.

Vous pouvez envoyer à Google:

  • Effectuer plusieurs tâches par lot par jour pour maintenir votre inventaire à jour
  • Un job par lot par jour et des API supplémentaires pour maintenir votre inventaire à jour.