查询 protobuf 数据

本文档提供了用于读取和查询存储在 Bigtable 中的协议缓冲区 (protobuf) 数据的常见查询模式示例。

在阅读本页面内容之前,请先熟悉以下内容:

示例数据

以下示例使用 Music 表,该表存储有关专辑和艺术家的信息。数据存储在名为 album_details 的列族中,带有 列限定符 album。列限定符包含 protobuf 消息。

protobuf 架构在以下 proto 文件中定义:

  • artist.proto

    syntax = "proto3";
    
    package package_name;
    
    message Artist {
     string name = 1;
    }
    
  • album.proto

    syntax = "proto3";
    
    package package_name;
    
    import "artist.proto";
    
    message Album {
     string title = 1;
     Artist artist = 2;
     int32 release_year = 3;
    }
    

因此,Bigtable 会为此表创建一个架构软件包,其中 包含以下 protobuf 文件描述符集 用于这些 protobuf 定义:

file {
  name: "artist.proto"
  package: "package_name"
  message_type {
    name: "Artist"
    field {
      name: "name"
      number: 1
      label: LABEL_OPTIONAL
      type: TYPE_STRING
      json_name: "name"
    }
  }
  syntax: "proto3"
}
file {
  name: "album.proto"
  package: "package_name"
  dependency: "artist.proto"
  message_type {
    name: "Album"
    field {
      name: "title"
      number: 1
      label: LABEL_OPTIONAL
      type: TYPE_STRING
      json_name: "title"
    }
    field {
      name: "artist"
      number: 2
      label: LABEL_OPTIONAL
      type: TYPE_MESSAGE
      type_name: ".package_name.Artist"
      json_name: "artist"
    }
    field {
      name: "release_year"
      number: 3
      label: LABEL_OPTIONAL
      type: TYPE_INT32
      json_name: "releaseYear"
    }
  }
  syntax: "proto3"
}

示例查询

以下示例展示了如何使用适用于 Bigtable 的 GoogleSQL 和 BigQuery 外部表查询 protobuf 数据。

将列转换为 protobuf 消息

您可以使用 CAST 运算符将 BYTES 值解读为 protobuf 消息。 为此,您必须提供 protobuf 消息的全名,格式如下: SCHEMA_BUNDLE_ID.FULLY_QUALIFIED_MESSAGE_NAME.

替换以下内容:

  • SCHEMA_BUNDLE_ID:您在创建架构软件包时为其分配的唯一 ID。
  • FULLY_QUALIFIED_MESSAGE_NAME:消息的全名,必须包含在 proto 文件中定义的软件包名称,例如 package_name.message_name

以下示例查询将 album 列转换为 Album protobuf 消息。此消息在 package_name 软件包中定义,并且是名为 bundle_name 的架构软件包的一部分:

SELECT
  CAST(album_details['album'] AS bundle_name.package_name.Album).title
FROM
  Music;

访问嵌套字段

您可以使用点表示法访问 protobuf 消息中的嵌套字段。

以下查询从 Album 消息中的嵌套 Artist 消息检索艺术家的姓名:

SELECT
  CAST(album_details['album'] AS bundle_name.package_name.Album).artist.name
FROM
  Music;

根据 protobuf 字段进行过滤

您可以使用 WHERE 子句根据 protobuf 消息中字段的值过滤行。

以下查询选择艺术家 Dana A. 的所有专辑:

SELECT
  *
FROM
  Music
WHERE
  CAST(album_details['album'] AS bundle_name.package_name.Album).artist.name = 'Dana A.';

聚合 protobuf 字段

您可以对 protobuf 消息中的数字字段使用聚合函数,例如 SUMAVGMINMAXCOUNT

以下查询计算表中所有专辑的平均发行年份:

SELECT
  AVG(CAST(album_details['album'] AS bundle_name.package_name.Album).release_year)
FROM
  Music;

按 protobuf 字段排序

您可以使用 ORDER BY 子句根据 protobuf 消息中的字段对结果集进行排序。

以下查询检索所有专辑,并按发行年份降序对其进行排序:

SELECT
  *
FROM
  Music
ORDER BY
  CAST(album_details['album'] AS bundle_name.package_name.Album).release_year DESC;

与视图搭配使用

您可以创建持续物化视图逻辑视图,读取 protobuf 数据。

以下命令会创建一个逻辑视图,该视图会提取 Album 消息中的所有字段:

QUERY="SELECT _key, CAST(album_details['album'] AS bundle_name.package_name.Album).* FROM Music"

gcloud bigtable logical-views create LOGICAL_VIEW_ID \
    --instance=INSTANCE_ID \
    --query=$QUERY

替换以下内容:

  • LOGICAL_VIEW_ID:引用架构软件包的逻辑视图的 ID。
  • INSTANCE_ID:您用于创建架构软件包的实例的 ID。

当视图引用架构软件包时,您必须先删除该视图,然后才能删除该软件包。此外,请勿将架构软件包更新为与现有软件包不向后兼容的新 protobuf 文件描述符集。

与 BigQuery 外部表搭配使用

您可以通过创建外部表,从 BigQuery 查询存储在 Bigtable 中的 protobuf 数据。创建外部表时,您可以将列类型指定为 JSON,将编码指定为 PROTO_BINARY,并将其与架构软件包相关联。此过程会将 protobuf 消息字节转换为等效的 JSON 数据,让您可以直接查询其字段。

以下示例展示了用于 创建 BigQuery 外部表 的表定义文件,该文件适用于 Music 表:

{
    "sourceFormat": "BIGTABLE",
    "sourceUris": [
        "https://googleapis.com/bigtable/projects/PROJECT_ID/instances/INSTANCE_ID/tables/Music"
    ],
    "bigtableOptions": {
        "columnFamilies" : [
            {
                "familyId": "album_details",
                "columns": [
                    {
                        "qualifierString": "album",
                        "type": "JSON",
                        "encoding": "PROTO_BINARY",
                        "protoConfig": {
                            "schemaBundleId": "bundle_name",
                            "protoMessageName": "package_name.Album"
                        }
                    }
                ]
            }
        ]
    }
}

创建外部表后,您可以在 BigQuery 中将 protobuf 数据作为 JSON 列进行查询。

以下查询从 BigQuery 外部表中检索 2022 年发行的所有专辑的标题:

SELECT JSON_VALUE(value, '$.title') AS title
FROM
`PROJECT_ID.DATASET.TABLE_NAME` AS t,
UNNEST(t.album_details.album.cell)
WHERE INT64(JSON_EXTRACT(value, '$.releaseYear')) = 2022;

后续步骤