这是与 Recommendations AI、Retail Search 和新的 Retail 控制台相关的文档。如需在受限 GA 阶段使用 Retail Search,请与 Cloud 销售人员联系

如果您仅使用 Recommendations AI,请保留在 Recommendations 控制台上并参阅 Recommendations AI 文档

更新 Retail Search 商品目录

虽然使用 Product 创建、读取、更新和删除 (CRUD) 方法可广泛修改 Product 的属性,但有一组 Product 方法可用于用于更新具有不同粒度级别的商品目录特定字段。以下 Product 字段被视为商品目录字段:

  • Product.price_info
  • Product.availability
  • Product.available_quantity
  • Product.fulfillment_info

商品目录更新方法

更改产品目录信息的频率要比更改目录信息的频率高得多。因此,我们提供了一套专门的方法来处理大量特定于商品目录的更新。这些方法是异步的,因为下游优化支持每个产品数百个并发更新,而不会影响性能。

增量更新

fulfillment_info 通常用于对 Product 的地点级 fulfillment 可用性进行编码。在某些情况下,某些特定地点的 fulfillment 可用性可能会发生变化,并且您可以决定发出描述此更改的更新,而不是使用 UpdateProduct 方法重新指定整个商品的履单信息。

在这种情况下,AddFulfillmentPlacesRemoveFulfillmentPlaces 方法可用于根据地点 ID 逐步更新商品的 fulfillment 更改为给定的 fulfillment 类型添加或移除资源。

Java

如需了解如何安装和使用 Retail 客户端库,请参阅 Retail 客户端库。如需了解详情,请参阅 Retail Java API 参考文档

public static AddFulfillmentPlacesResponse addFulfillmentPlaces(
    Product productToUpdate, String fulfillmentInfoType, ImmutableList<String> placeIds)
    throws IOException, InterruptedException, ExecutionException {
  ProductServiceClient productClient = getProductServiceClient();

  AddFulfillmentPlacesRequest request = AddFulfillmentPlacesRequest.newBuilder()
      .setProduct(productToUpdate.getName())
      .setType(fulfillmentInfoType)
      .addAllPlaceIds(placeIds)
      .setAddTime(Timestamps.fromMillis(System.currentTimeMillis()))
      .build();

  AddFulfillmentPlacesResponse response = productClient
      .addFulfillmentPlacesAsync(request).get();

  productClient.shutdownNow();
  productClient.awaitTermination(2, TimeUnit.SECONDS);

  return response;
}

Proto

  {
    product: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch/products/p123"
    type: "pickup-in-store"
    place_ids: "store0"
    place_ids: "store1"
    add_time: {
      seconds: 100
      nanos: 100
    }
    allow_missing: true
  }
  

此示例 AddFulfillmentPlacesRequest 添加了 fulfillment 类型 "pickup-in- store",以便为指定商品放置 ID "store0""store1"。由于 AddFulfillmentPlacesRequest.allow_missing 设置为 true,因此即使商品尚不存在,系统也会存储更新后的商品目录信息,以供最终创建商品时使用。更新带有 AddFulfillmentPlacesRequest.add_time 时间戳,以防止过时更新覆盖这些地点 ID 的 fulfillment 状态。以下各部分将更详细地讨论这些功能。

RemoveFulfillmentPlacesRequest 的行为完全相同,架构非常相似。

非增量更新

不能增量更新 price_infoavailabilityavailable_quantity,因为它们代表商品级商品目录,而不是地点级信息。此外,可能希望向 fulfillment_info 发出非增量更新,而不是仅增量更新。在这种情况下,建议使用 SetInventory 方法。

Java

如需了解如何安装和使用 Retail 客户端库,请参阅 Retail 客户端库。如需了解详情,请参阅 Retail Java API 参考文档

public static SetInventoryResponse setInventoryWithMask(Product productToUpdate,
    FieldMask updateMask)
    throws IOException, ExecutionException, InterruptedException {
  ProductServiceClient productClient = getProductServiceClient();

  SetInventoryRequest request = SetInventoryRequest.newBuilder()
      .setInventory(productToUpdate)
      .setSetMask(updateMask)
      .setSetTime(Timestamps.fromMillis(System.currentTimeMillis()))
      .setAllowMissing(true)
      .build();

  SetInventoryResponse response = productClient.setInventoryAsync(request).get();

  productClient.shutdownNow();
  productClient.awaitTermination(2, TimeUnit.SECONDS);

  return response;
}

Proto

  {
    product: {
      name: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch/products/p123"
      availability: IN_STOCK
      fulfillment_info: {
        type: "pickup-in-store"
        place_ids: "store0"
        place_ids: "store1"
        place_ids: "store2"
        place_ids: "store3"
      }
      fulfillment_info: {
        type: "same-day-delivery"
      }
    }
    set_time: {
      seconds: 100
      nanos: 100
    }
    set_mask: {
      paths: "availability"
      paths: "fulfillment_info"
    }
    allow_missing: true
  }
  

在此特定请求中,SetInventoryRequest.product.fulfillment_info 字段是每个 fulfillment 类型符合条件的地点 ID 的完整说明,而不是增量规范。更新为 "same-day-delivery" 表示没有地点 ID 适用于此产品此 fulfillment 类型。所有其他 fulfillment 类型不会在此请求中更新。

默认情况下,如果 SetInventory.set_mask 未设置或为空,SetInventory 将更新所有库存字段。如果掩码不为空或 SetInventoryRequest.set_mask 中未明确列出库存字段,则系统会在更新请求中忽略该库存字段的任何指定值。

与增量更新一样,SetInventoryRequest.set_time 字段可用于设置更新时间,以与所有更新后的商品目录字段的上次记录更新时间相对比。

商品目录更新的时间戳保护措施

有几种不同的路径可以更新商品的库存字段,并防止出现无序更新,每个库存字段都与最新的更新时间相关联。

系统记录了 price_infoavailabilityavailable_quantity(fulfillment_info.place_ids, fulfillment_info.type) 的每一对的最新更新时间。

调用 AddFulfillmentPlacesRemoveFulfillmentPlacesSetInventory 方法可让调用方指定请求发出的更新时间。系统会将此更新时间与为相关商品目录字段记录的最新更新时间进行比较;当更新时间完全晚于最新更新时间时,才会提交更新。

例如,假设地点 ID "store1" 启用了 fulfillment 类型 "pickup-in- store",并且上次记录的更新时间设置为 T。如果 RemoveFulfillmentPlacesRequest.type = "pickup-in-store"RemoveFulfillmentPlacesRequest.place_ids 包含 "store1",则当且仅当 RemoveFulfillmentPlacesRequest.remove_time 晚于 T 时,请求才会从 "store1" 清除 "pickup-in-store"AddFulfillmentPlacesRequests 也是如此。

SetInventory 的运行方式与更新 price_infoavailabilityavailable_quantity 类似。更新 fulfillment_info 时,SetInventoryRequest 会隐式要求为给定 fulfillment 类型添加所有指定的地点 ID,并移除所有未指定的现有地点 ID。

因此,在处理 SetInventoryRequest 时,对于指定的每个 fulfillment 类型,fulfillment_info 更新都会隐式转换为 AddFulfillmentPlacesRequestRemoveFulfillmentPlacesRequest。也就是说,如果任何具有 fulfillment "pickup-in-store" 的现有地点 "store1" 的上次更新时间 T 晚于 SetInventoryRequest.set_time,将不会对 "store1""pickup-in-store" 应用隐式添加/移除。

预加载商品目录信息

每种库存更新方法都允许调用者在请求中设置 allow_missing。将 allow_missing 设置为 true 时,将按照方法规范处理对不存在的 Product 的库存更新,就像存在 Product 一样。如果未在此时间范围内通过 CreateProduct 创建相应的 Product,则商品目录信息将最多保留两天。

Java

public static SetInventoryResponse setInventory(Product productToUpdate)
    throws IOException, ExecutionException, InterruptedException {
  ProductServiceClient productClient = getProductServiceClient();

  SetInventoryRequest request = SetInventoryRequest.newBuilder()
      .setInventory(productToUpdate)
      .setSetTime(Timestamps.fromMillis(System.currentTimeMillis()))
      .setAllowMissing(true)
      .build();

  SetInventoryResponse response = productClient.setInventoryAsync(request).get();

  productClient.shutdownNow();
  productClient.awaitTermination(2, TimeUnit.SECONDS);

  return response;
}

何时使用 Product 方法

虽然可以使用产品 CRUD 方法更新商品目录字段,但调用者应该明确了解对现有或现有商品目录信息的影响。

它们是同步方法,这意味着用于商品目录方法的下游优化不适用,并且可能依赖于依靠这些方法频繁更新商品目录成本。尽可能使用被提及的商品目录更新方法。

CreateProduct

如果在设置任何广告资源字段的情况下调用 CreateProductCreateProductRequest.product 中提供的值将替换这些字段的预加载值。如果未设置库存字段,将自动使用任何预先存在的库存信息。

此外,已替换商品目录字段的最新更新时间将重置为方法调用的时间。

CreateProduct(包含预加载的商品目录)

PROTO

{
  parent: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch"
  product_id: "p123"
  product: {
    name: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch/products/p123"
    title: "some product"
    type: VARIANT
  }
}

在此示例中,创建的产品未设置任何库存字段,这意味着如果使用库存更新方法进行更新,系统将自动使用任何预加载的库存信息。这在库存更新与目录更新分离且您希望新创建的 Product 与任何现有库存信息同步时非常有用。

CreateProduct - 具有明确的商品目录

PROTO

{
  parent: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch"
  product_id: "p123"
  product: {
    name: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch/products/p123"
    title: "some product"
    type: VARIANT
    availability: OUT_OF_STOCK
    fulfillment_info: {
      type: "pickup-in-store"
    }
    fulfillment_info: {
      type: "same-day-delivery"
    }
  }
}

在此示例中,使用明确设置的库存字段创建 Product。这些字段将覆盖预先存在的任何值,并忽略相应字段的最新更新时间。因此,新创建的 Product 保证可用性设置为 OUT_OF_STOCK,并且没有任何地点 ID 支持 fulfillment 类型 "pickup-in-store""same-day-delivery"

如果不确定所有预加载的商品目录信息是否准确,并且宁愿在 Product 创建时显式设置商品目录以完全同步目录和商品目录,则带有商品目录信息的 CreateProduct 可能会有所帮助。

UpdateProduct

调用 UpdateProduct 且字段掩码 UpdateProductRequest.update_mask 包含任何库存字段时,UpdateProductRequest.product 中提供的值将替换任何预加载值。

此外,已替换商品目录字段的最新更新时间将重置为方法调用的时间。

PROTO

{
  product: {
    name: "projects/123/locations/global/catalogs/default_catalog/branches/default_branch/products/p123"
    availability: IN_STOCK
    fulfillment_info: {
      type: "pickup-in-store"
      place_ids: "store0"
      place_ids: "store1"
      place_ids: "store2"
      place_ids: "store3"
    }
    fulfillment_info: {
      type: "same-day-delivery"
    }
  }
  update_mask: {
    paths: "availability"
    paths: "fulfillment_info"
  }
}

此示例非常类似于 SetInventory 示例,不同之处在于无论每个商品目录字段的最新更新时间,系统保证始终应用更新。

如果在忽略时间戳保护的同时需要全面同步商品目录信息,则 UpdateProduct 能发挥作用。

虽然可以通过将 UpdateProductRequest.allow_missing 设置为 true 来执行 Product 插入,从而使用 UpdateProduct 预加载商品目录信息,但该方法需要设置特定目录字段,如 UpdateProductRequest.product.title。因此,建议使用商品目录更新方法预加载用例。

DeleteProduct

调用 DeleteProduct 时,将删除 DeleteProductRequest.name 中指定的产品的所有现有商品目录信息,包括每个商品目录字段的最新更新时间的所有记录。