Pembaruan inventaris inkremental v1

Bagian ini menjelaskan cara mengirim pembaruan feed yang sensitif terhadap waktu ke Google. Incremental Updates API memungkinkan Anda memperbarui dan menghapus entity di feed hampir secara real time.

Fungsi ini terutama ditujukan untuk update yang tidak dapat Anda prediksi, seperti penutupan darurat. Sebagai aturan, setiap perubahan yang dikirimkan melalui Incremental Updates API harus berupa perubahan yang harus ditayangkan dalam waktu tidak lebih dari satu minggu. Jika perubahan tidak perlu segera diterapkan, Anda dapat menggunakan update batch. Update inkremental diproses dalam waktu tidak lebih dari lima menit.

Penyiapan

Untuk menerapkan update inkremental, lakukan hal berikut:

  1. Ikuti langkah-langkah yang diuraikan dalam Membuat dan menyiapkan project untuk membuat project.
  2. Ikuti langkah-langkah yang diuraikan di Menyiapkan akun layanan untuk membuat akun layanan. Perhatikan bahwa Anda harus menjadi "Pemilik" project untuk menambahkan peran "Editor" untuk akun layanan
  3. (Opsional, tetapi direkomendasikan) Instal library Klien Google dalam bahasa pilihan Anda untuk memfasilitasi penggunaan OAuth 2.0 saat memanggil API. Contoh kode yang disertakan di bawah menggunakan library ini. Jika tidak, Anda harus menangani pertukaran token secara manual seperti yang dijelaskan dalam Menggunakan OAuth 2.0 untuk Mengakses Google API.

Endpoint

Untuk memberi tahu Google tentang update, buat permintaan POST HTTP ke Incremental Updates API dan sertakan payload update dan penambahan. Skema inventaris yang Anda gunakan menentukan endpoint mana yang akan menerima permintaan Anda:

inventaris v2

https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/TYPE/ENTITY_ID:push

Inventaris v1

https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/ENTITY_ID:push

Untuk menghapus entity, buat permintaan HTTP DELETE ke endpoint berikut yang sesuai dengan skema inventaris yang Anda gunakan:

inventaris v2

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

Inventaris v1

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

Dalam permintaan di atas, ganti hal berikut:

  • PROJECT_ID: Project ID Google Cloud yang terkait dengan project yang Anda buat di Membuat dan menyiapkan project.
  • TYPE (khusus skema inventaris v2): Jenis entity (properti @type) objek dalam feed data yang ingin Anda perbarui.
  • ENTITY_ID: ID entity yang disertakan dalam payload. Pastikan untuk mengenkode ID entitas Anda ke dalam URL.
  • DELETE_TIME (khusus endpoint hapus): Kolom opsional untuk menunjukkan waktu entitas dihapus di sistem Anda (defaultnya adalah saat permintaan diterima). Nilai waktu tidak boleh di masa mendatang. Saat mengirim entity melalui panggilan inkremental, pembuatan versi entity juga menggunakan kolom delete_time jika terjadi panggilan penghapusan. Format nilai ini sebagai yyyy-mm-ddTHH:mm:ssZ

Misalnya, Anda memiliki project dengan ID "delivery-provider-id" yang menggunakan skema inventaris v2. Anda ingin membuat perubahan pada restoran dengan jenis entity restoran "MenuSection" dan ID entity "menuSection_122". Endpoint untuk pembaruan data Anda adalah sebagai berikut:

https://actions.googleapis.com/v2/apps/delivery-provider-id/entities/MenuSection/menuSection_122:push

Untuk menghapus entitas yang sama ini, Anda harus melakukan panggilan API HTTP DELETE ini:

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

Permintaan sandbox

Untuk permintaan sandbox, ikuti panduan di Endpoint di atas, tetapi buat permintaan ke /v2/sandbox/apps/, bukan ke /v2/apps/. Misalnya, permintaan penghapusan sandbox untuk skema inventaris v2 disusun sebagai berikut:

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

Pembaruan dan penambahan

Feed batch harian Anda juga harus berisi perubahan apa pun yang dikirim melalui API ini. Jika tidak, update batch akan menimpa perubahan inkremental Anda.

Payload

Setiap permintaan POST harus menyertakan parameter permintaan beserta payload JSON yang berisi data terstruktur dari jenis entity apa pun yang tercantum dalam skema inventaris.

JSON akan terlihat sama seperti di feed batch, dengan perbedaan berikut:

  • Ukuran isi payload tidak boleh melebihi 5 MB. Serupa dengan feed batch, sebaiknya hapus spasi kosong agar lebih banyak data yang muat.
  • Envelopnya adalah sebagai berikut:
{
  "entity": {
    "data":"ENTITY_DATA",
    "vertical":"FOODORDERING"
  },
  "update_time":"UPDATE_TIMESTAMP"
}

Dalam payload di atas, ganti kode berikut:

  • ENTITY_DATA: Entitas dalam format JSON yang diserialisasi sebagai string. Entitas JSON-LD harus diteruskan sebagai string di kolom data.
  • UPDATE_TIMESTAMP (opsional): Stempel waktu saat entity diperbarui di sistem Anda. Nilai waktu tidak boleh di masa mendatang. Stempel waktu default adalah saat Google menerima permintaan. Saat mengirim entity melalui permintaan tambahan, pembuatan versi entity juga menggunakan kolom update_time jika ada permintaan penambahan/pembaruan.

Memperbarui entity

Contoh 1: Memperbarui restoran

Misalnya, Anda perlu memperbarui nomor telepon restoran dengan segera. Pembaruan Anda berisi JSON untuk seluruh restoran.

Pertimbangkan feed batch yang terlihat seperti berikut:

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

Kemudian, pembaruan inkremental Anda melalui HTTP POST akan menjadi seperti berikut:

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

Contoh 2: Memperbarui harga item menu

Misalnya, Anda perlu mengubah harga item menu. Seperti pada Contoh 1, pembaruan Anda harus berisi JSON untuk seluruh entitas tingkat teratas (menu), dan feed menggunakan skema inventaris v1.

Pertimbangkan feed batch yang terlihat seperti berikut:

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

Kemudian, update inkremental Anda melalui POST akan menjadi seperti berikut:

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

Menambahkan entity

Untuk menambahkan entity, hindari penggunaan update inventaris. Sebagai gantinya, gunakan proses feed batch seperti yang dijelaskan untuk skema inventaris v2.

Menghapus entity

Untuk menghapus entitas tingkat atas, Anda menggunakan endpoint yang sedikit dimodifikasi, dan menggunakan HTTP DELETE, bukan HTTP POST dalam permintaan.

Jangan gunakan HTTP DELETE untuk menghapus sub-entity dalam entity tingkat teratas, seperti item menu dalam menu. Sebagai gantinya, anggap penghapusan sub-entity sebagai update ke entity tingkat teratas tempat sub-entity dihapus dari daftar atau parameter yang relevan.

Contoh 1: Menghapus entity tingkat teratas

Pertimbangkan situasi saat Anda ingin menghapus restoran di feed yang menggunakan skema inventaris v1. Anda juga harus menghapus layanan dan menunya.

Contoh endpoint untuk entitas menu dengan 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

Contoh endpoint untuk entitas restoran dengan 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

Contoh endpoint untuk entitas layanan dengan 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
}

Contoh 2: Menghapus sub-entity

Untuk menghapus sub-entitas dari dalam entitas tingkat teratas, Anda mengirim entitas tingkat atas dengan sub-entitas yang dihapus dari kolom yang sesuai. Contoh berikut mengasumsikan feed menggunakan skema inventaris v1.

Misalnya, untuk menghapus area layanan, perbarui layanan dengan area layanan yang dihapus dari daftar 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"
  }
}

Kode respons API

Panggilan yang berhasil tidak berarti bahwa feed valid atau benar, hanya bahwa panggilan API telah dilakukan. Panggilan yang berhasil akan menerima kode respons HTTP 200, beserta isi respons kosong:

{}

Untuk kegagalan, kode respons HTTP tidak akan menjadi 200, dan isi respons menunjukkan masalah yang terjadi.

Misalnya, jika pengguna telah menetapkan nilai "vertical" dalam amplop ke FAKE_VERTICAL, Anda akan menerima pesan di bawah ini:

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

Contoh kode

Berikut adalah beberapa contoh cara menggunakan Incremental Updates API dalam berbagai bahasa. Contoh ini menggunakan Library Autentikasi Google, dan mengasumsikan feed menggunakan skema inventaris v1. Untuk solusi alternatif, lihat Menggunakan OAuth 2.0 untuk Aplikasi Server ke Server.

Mengupdate entity

Node.js

Kode ini menggunakan library autentikasi Google untuk 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

Kode ini menggunakan library autentikasi Google untuk 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

Kode ini menggunakan library autentikasi Google untuk 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);
}

Menghapus entity

Node.js

Kode ini menggunakan library autentikasi Google untuk 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

Kode ini menggunakan library autentikasi Google untuk 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

Kode ini menggunakan library autentikasi Google untuk 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));
}

Kasus penggunaan

Kasus penggunaan berikut adalah contoh pembaruan inkremental, pembaruan feed lengkap, dan konten di tingkat tinggi dalam panggilan API:

Skenario Entitas tingkat teratas Deskripsi dan efek
Menonaktifkan layanan DisabledService

Anda perlu menonaktifkan layanan karena alasan yang tidak terduga.

Pembaruan inkremental: Kirim entitas Service yang dimaksud dengan @type diubah menjadi DisabledService, tetapi pertahankan properti lainnya tetap sama.

Feed lengkap: Pastikan untuk memperbarui entitas dari feed lengkap agar @type ditetapkan ke DisabledService sebelum pengambilan berikutnya oleh Google. Jika tidak, entitas akan diaktifkan kembali.

Stok item tertentu habis Menu Pembaruan inkremental: Kirim entitas Menu yang mengenkapsulasi dengan offer.inventoryLevel ditetapkan ke 0 untuk MenuItem yang diberikan, dan semua data lainnya tidak berubah.
Perubahan harga item menu Menu Pembaruan inkremental: Kirim entity Menu yang mengenkapsulasi dengan offer.price ditetapkan ke harga yang diperbarui untuk MenuItem tertentu, dan semua data lainnya tidak berubah.

Menambahkan entity tingkat teratas baru

Hanya berlaku untuk entity jenis Menu, Restaurant, dan Service.

Menu, Restaurant, Service

Misalnya, Anda perlu menambahkan menu baru ke restoran.

Pembaruan inkremental: Kirim entitas menu baru, beserta entitas restoran dengan kolom hasMenu yang diperbarui.

Menghapus entity tingkat teratas secara permanen

Hanya berlaku untuk entity jenis Menu, Restaurant, dan Service.

Menu, Restaurant, Service

Update inkremental: Kirim penghapusan eksplisit.

Feed lengkap: Pastikan untuk menghapus entitas dari feed lengkap sebelum pengambilan berikutnya oleh Google. Jika tidak, entitas akan ditambahkan kembali.

Menambahkan area pengiriman baru di Service tertentu Service Feed inkremental: Kirimkan entity Service yang dimaksud dengan semua kolomnya tetap utuh, seperti yang biasa Anda lakukan dalam feed lengkap, dengan area pengiriman baru yang ditentukan dalam areaServed dari Service.
Memperbarui perkiraan waktu tiba pengiriman di Service Service Feed inkremental: Kirim Service yang sama seperti di feed, kecuali hoursAvailable.deliveryHours-nya diperbarui sebagaimana mestinya.
Memperbarui harga pengiriman di Service Service Feed inkremental: Mengirim Service lengkap dengan offers.priceSpecification.price yang diperbarui.
Memperbarui jam buka untuk pesan antar atau bawa pulang di Service Service Feed inkremental: Kirim Service yang sama seperti di feed, kecuali hoursAvailable-nya diperbarui sebagaimana mestinya.
Service (ubah jumlah pesanan minimum) Service Feed inkremental: Mengirim Service lengkap dengan Service.offers.priceSpecification.eligibleTransactionVolume yang diperbarui
Menghapus MenuItem secara permanen Menu Feed inkremental: Kirim Menu yang sama seperti dalam feed, tetapi dengan MenuItem ini dihapus dari daftar hasMenuItems.

SLO tentang waktu pemrosesan untuk tugas batch dan update inkremental

Entitas yang ditambahkan melalui update massal atau inkremental akan diproses dalam 1-2 hari. Entitas yang diperbarui atau dihapus melalui batch akan diproses dalam 2 jam, sedangkan entitas yang diperbarui melalui update inkremental akan diproses dalam 5 menit. Entitas yang tidak berlaku akan dihapus dalam 7 hari.

Anda dapat mengirimkan ke Google:

  • Beberapa tugas batch per hari untuk terus memperbarui inventaris Anda, ATAU
  • Satu tugas batch per hari dan Incremental API untuk terus memperbarui inventaris Anda.