Cette section explique comment envoyer à Google des mises à jour urgentes de vos flux. Cette API vous permet de mettre à jour et de supprimer des entités dans vos flux en temps quasi réel.
Cette fonctionnalité est principalement destinée aux mises à jour que vous ne pouvez pas prévoir, comme les fermetures d'urgence. En règle générale, toute modification envoyée via l'API incrémentale Updates doit être mise en ligne sous une semaine maximum. Si votre modification n'a pas besoin d'être appliquée immédiatement, vous pouvez effectuer une mise à jour par lot à la place. Les mises à jour incrémentielles sont traitées en cinq minutes au maximum.
Prérequis
Pour implémenter des mises à jour incrémentielles, procédez comme suit:
- Suivez les étapes décrites dans Créer et configurer un projet pour créer un projet.
- Suivez les étapes décrites dans la section Configurer un compte de service pour créer un compte de service. Notez que vous devez être "Propriétaire" du projet pour ajouter un rôle "Éditeur" au compte de service.
- (Facultatif, mais recommandé) Installez la bibliothèque cliente Google dans le langage de votre choix pour faciliter l'utilisation d'OAuth 2.0 lorsque vous appelez l'API. Les exemples de code ci-dessous utilisent ces bibliothèques. Sinon, vous devrez gérer les échanges de jetons manuellement, comme décrit dans la section Utiliser OAuth 2.0 pour accéder aux API Google.
Point de terminaison
Pour avertir Google d'une mise à jour, envoyez une requête HTTP POST à l'API Ongoing Updates en incluant une charge utile de mises à jour et d'ajouts. Le schéma d'inventaire que vous utilisez détermine le point de terminaison auquel envoyer votre requête:
Inventaire v2
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/TYPE/ENTITY_ID:push
Inventaire v1
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/ENTITY_ID:push
Pour supprimer une entité, envoyez une requête HTTP DELETE au point de terminaison suivant, qui correspond au schéma d'inventaire que vous utilisez:
Inventaire v2
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/TYPE/ENTITY_ID?entity.vertical=FOODORDERING&delete_time=DELETE_TIME
Inventaire v1
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/ENTITY_ID?entity.vertical=FOODORDERING&delete_time=DELETE_TIME
Dans les requêtes ci-dessus, remplacez les éléments suivants:
- PROJECT_ID: ID du projet Google Cloud associé au projet que vous avez créé dans la section Créer et configurer un projet.
- TYPE (schéma d'inventaire v2 uniquement): type d'entité (propriété
@type
) de l'objet de votre flux de données que vous souhaitez mettre à jour. - ENTITY_ID: ID de l'entité incluse dans la charge utile. Veillez à encoder votre ID d'entité au format URL.
- DELETE_TIME (supprimer le point de terminaison uniquement): champ facultatif pour indiquer l'heure à laquelle l'entité a été supprimée de vos systèmes (la valeur par défaut correspond à la réception de la requête). 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é utilise également le champ
delete_time
dans le cas d'un appel de suppression. Mettez en forme cette valeur au formatyyyy-mm-ddTHH:mm:ssZ
.
Par exemple, vous disposez d'un projet avec l'ID "delivery-provider-id" qui utilise le schéma d'inventaire v2. Vous souhaitez modifier le restaurant avec le type d'entité de restaurant "MenuSection" et l'ID d'entité "menuSection_122". Le point de terminaison pour les mises à jour de vos données est le suivant:
https://actions.googleapis.com/v2/apps/delivery-provider-id/entities/MenuSection/menuSection_122:push
Pour supprimer cette même entité, vous devez effectuer cet appel d'API HTTP DELETE:
https://actions.googleapis.com/v2/apps/delivery-provider-id/entities/MenuSection/menuSection_122?entity.vertical=FOODORDERING
Requêtes de bac à sable
Pour les requêtes de bac à sable, suivez les instructions de la section Point de terminaison ci-dessus, mais envoyez des requêtes à /v2/sandbox/apps/
au lieu de /v2/apps/
. Par exemple, une demande de suppression de bac à sable pour le schéma d'inventaire v2 se présente comme suit:
https://actions.googleapis.com/v2/sandbox/apps/PROJECT_ID/entities/TYPE/ENTITY_ID?entity.vertical=FOODORDERING&delete_time=DELETE_TIME
Mises à jour et ajouts
Vos flux par lot quotidiens doivent également contenir toutes les modifications envoyées via cette API. Sinon, vos mises à jour groupées écraseront vos modifications incrémentielles.
Charge utile
Chaque requête POST doit inclure les paramètres de requête ainsi que la charge utile JSON contenant les données structurées de tout type d'entité répertorié dans le schéma d'inventaire.
Le fichier JSON doit être identique à celui du flux par lot, avec les différences suivantes:
- La taille du corps de la charge utile ne doit pas dépasser 5 Mo. Comme pour les flux par lot, nous vous suggérons de supprimer les espaces blancs afin d'ajuster plus de données.
- L'enveloppe se présente comme suit:
{ "entity": { "data":"ENTITY_DATA", "vertical":"FOODORDERING" }, "update_time":"UPDATE_TIMESTAMP" }
Dans la charge utile ci-dessus, remplacez ce qui suit:
- ENTITY_DATA: entité au format JSON sérialisée en tant que chaîne. L'entité JSON-LD doit être transmise sous forme de chaîne dans le champ
data
. - UPDATE_TIMESTAMP (facultatif): code temporel de la mise à jour de l'entité dans vos systèmes. La valeur de l'heure ne doit pas se situer dans le futur. L'horodatage par défaut correspond au moment où Google reçoit la requête. Lors de l'envoi d'une entité via une requête incrémentielle, la gestion des versions d'entité utilise également le champ
update_time
dans le cas d'une requête d'ajout/de mise à jour.
Mettre à jour une entité
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 mise à jour contient le fichier JSON de l'ensemble du restaurant.
Prenons l'exemple d'un flux groupé semblable à celui-ci:
{ "@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 }
La mise à jour incrémentielle par HTTP POST se présenterait alors comme suit:
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" } }
Exemple 2: 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, votre mise à jour doit contenir le code JSON de l'entité de premier niveau entière (le menu), et le flux utilise le schéma d'inventaire v1.
Prenons l'exemple d'un flux groupé semblable à celui-ci:
{ "@type": "MenuItemOffer", "@id": "menuitemoffer6680262", "sku": "offer-cola", "menuItemId": "menuitem896532", "price": 3.00, "priceCurrency": "USD" }
La mise à jour incrémentielle via POST se présenterait alors comme suit:
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" } }
Ajouter une entité
Pour ajouter des entités, évitez d'utiliser les mises à jour d'inventaire. Utilisez plutôt le processus de flux par lot comme décrit dans le schéma d'inventaire v2.
Supprimer une entité
Pour supprimer les entités de niveau supérieur, utilisez un point de terminaison légèrement modifié, et utilisez HTTP DELETE au lieu de HTTP POST dans la requête.
N'utilisez pas HTTP DELETE pour supprimer une sous-entité d'une entité de niveau supérieur, comme un élément de menu dans un menu. Traitez plutôt la suppression des sous-entités comme une mise à jour d'une entité de niveau supérieur dans laquelle la sous-entité est supprimée de la liste ou du paramètre correspondant.
Exemple 1: Supprimer une entité de niveau supérieur
Imaginons que vous souhaitiez supprimer un restaurant dans un flux utilisant le schéma d'inventaire v1. Vous devez également supprimer ses services et menus.
Exemple de point de terminaison pour une entité de menu ayant l'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
Exemple de point de terminaison pour une entité de restaurant ayant l'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
Exemple de point de terminaison pour une entité de service ayant l'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
}
Exemple 2: Supprimer des sous-entités
Pour supprimer une sous-entité d'une entité de niveau supérieur, envoyez l'entité de niveau supérieur en supprimant la sous-entité du champ correspondant. L'exemple suivant suppose que le flux utilise le schéma d'inventaire v1.
Par exemple, pour supprimer une zone desservie, vous devez la mettre à jour en la supprimant de la liste 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"
}
}
Codes de réponse de l'API
Un appel réussi ne signifie pas que le flux est valide ou correct, mais uniquement que l'appel d'API a été effectué. Les appels réussis reçoivent un code de réponse HTTP 200, ainsi qu'un corps de réponse vide:
{}
En cas d'échec, le code de réponse HTTP ne sera pas 200 et le corps de la réponse indiquera le problème.
Par exemple, si l'utilisateur a défini la valeur "verticale" dans l'enveloppe sur FAKE_VERTICAL
, le message ci-dessous s'affiche:
{
"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 laissées à jour incrémentales dans différents langages. Ces exemples utilisent les bibliothèques Google Auth et supposent la présence d'un flux à l'aide du schéma d'inventaire v1. Pour trouver d'autres solutions, reportez-vous à la page 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 = '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
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 = '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
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 = "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); }
Suppression d'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
Les cas d'utilisation suivants sont des exemples de mises à jour incrémentielles, de mises à jour de flux complètes et du contenu au haut niveau dans l'appel d'API:
Scénario | Entité de niveau supérieur | Description et effets |
---|---|---|
Désactiver un service | DisabledService |
Vous devez désactiver un service pour une raison imprévue. Mises à jour incrémentielles:envoyez l'entité Flux complets:veillez à mettre à jour l'entité à partir des flux complets en définissant |
Un article spécifique n'est pas disponible | Menu |
Mises à jour incrémentielles:envoie l'entité Menu d'encapsulation avec offer.inventoryLevel défini sur 0 pour le MenuItem donné, et toutes les autres données inchangées. |
Changement de prix d'un élément de menu | Menu |
Mises à jour incrémentielles:envoie l'entité Menu encapsulée avec offer.price défini sur le prix mis à jour pour le MenuItem donné, et toutes les autres données non modifiées. |
Ajouter une entité de niveau supérieur Ne s'applique qu'aux entités de types |
Menu , Restaurant et Service |
Par exemple, vous devez ajouter un nouveau menu à un restaurant. Mises à jour incrémentielles:la nouvelle entité de menu, ainsi que l'entité de restaurant et son champ |
Supprimer définitivement l'entité de niveau supérieur Ne s'applique qu'aux entités de types |
Menu , Restaurant et Service |
Mises à jour incrémentielles:envoyez une suppression explicite. Flux complets:veillez à supprimer l'entité des flux complets avant la prochaine extraction par Google, sinon elle sera de nouveau ajoutée. |
Ajouter une zone de livraison dans un Service spécifique |
Service |
Flux incrémentiels:envoyez l'entité Service en question avec tous ses champs intacts, comme vous le feriez normalement dans les flux complets, avec une nouvelle zone de livraison spécifiée dans un délai de areaServed à partir du Service . |
Modifier l'heure d'arrivée prévue à Service |
Service |
Flux incrémentiels:envoyez l'élément Service de la même manière que dans les flux, sauf que son hoursAvailable.deliveryHours est mis à jour en conséquence. |
Modifier les prix de livraison (Service ) |
Service |
Flux incrémentiels:envoyez la version Service complète avec la version offers.priceSpecification.price mise à jour. |
Modifier les horaires de livraison ou de vente à emporter dans Service |
Service |
Flux incrémentiels:envoyez l'élément Service de la même manière que dans les flux, sauf que son hoursAvailable est mis à jour en conséquence. |
Service (modifier le montant minimal de commande) |
Service |
Flux incrémentiels:envoyer la version Service complète avec la valeur Service.offers.priceSpecification.eligibleTransactionVolume mise à jour |
Supprimer MenuItem définitivement |
Menu |
Flux incrémentiels:envoyez l'élément Menu de la même manière que dans les flux, mais en supprimant cet élément MenuItem de la liste hasMenuItems . |
SLO concernant le temps de traitement des jobs par lot et des mises à jour incrémentielles
Une entité ajoutée par le biais d'une mise à jour par lot ou incrémentielle est traitée en un à deux jours. Une entité mise à jour ou supprimée par lot est traitée en deux heures, tandis qu'une entité mise à jour par le biais d'une mise à jour incrémentielle est traitée en cinq minutes. Une entité obsolète est supprimée au bout de sept jours.
Vous pouvez envoyer à Google:
- plusieurs jobs par lot par jour pour maintenir votre inventaire à jour, OU
- Une tâche par lot par jour et des API incrémentielles pour maintenir votre inventaire à jour.