使用 Firebase 进行缓存

Looker Studio 拥有自己的报告缓存系统。创建连接器时,您可以实现自定义缓存,以加快报告生成速度并避免 APR 速率限制。

例如,您要创建一个连接器,用于提供历史天气数据 查看过去 7 天的数据。您的连接器 但用于从中提取数据的外部 API 的速率很严格 限制。API 每天只更新其数据,因此对于特定的邮政编码, 无需在一天内多次提取相同的数据。使用此 解决方案指南,您可以为每个邮政编码实现每日缓存。

要求

  • 一个 Firebase 实时数据库。如果您无权访问任何实时数据库,请创建一个 Google Cloud Platform (GCP) 项目,并按照入门指南创建自己的 Firebase Realtime Database 实例。
  • 一个用于从 Firebase Realtime 读取和写入数据的 GCP 服务账号 数据库。
  • 一个可从来源中提取数据的社区连接器。

限制

  • 此解决方案无法与 Looker Studio 高级服务搭配使用。时间 您使用 Looker Studio 高级服务时,您在应用中提供的连接器代码 脚本无权访问这些数据。因此您无法缓存数据 使用 Apps 脚本编写代码。
  • 报告编辑者和查看者无法重置该特定缓存。

解决方案

实现服务账号

  1. 在 Google Cloud 项目中创建一个服务账号
  2. 确保此服务账号在 Cloud 项目中具有 BigQuery 访问权限。
    • 必需的身份和访问权限管理 (IAM) 角色:Firebase Admin
  3. 下载 JSON 文件以获取服务账号密钥。将文件的内容存储在连接器项目的脚本属性中。添加 键,应与 Apps 脚本界面中的以下内容类似:
    在脚本属性中保存服务账号密钥
  4. 在 Apps 脚本项目中添加适用于 Apps 脚本的 OAuth2 库。
  5. 为服务账号实现必需的 OAuth2 代码:
firestore-cache/src/firebase.js
var SERVICE_ACCOUNT_CREDS = 'SERVICE_ACCOUNT_CREDS';
var SERVICE_ACCOUNT_KEY = 'private_key';
var SERVICE_ACCOUNT_EMAIL = 'client_email';
var BILLING_PROJECT_ID = 'project_id';

var scriptProperties = PropertiesService.getScriptProperties();

/**
 * Copy the entire credentials JSON file from creating a service account in GCP.
 * Service account should have `Firebase Admin` IAM role.
 */
function getServiceAccountCreds() {
  return JSON.parse(scriptProperties.getProperty(SERVICE_ACCOUNT_CREDS));
}

function getOauthService() {
  var serviceAccountCreds = getServiceAccountCreds();
  var serviceAccountKey = serviceAccountCreds[SERVICE_ACCOUNT_KEY];
  var serviceAccountEmail = serviceAccountCreds[SERVICE_ACCOUNT_EMAIL];

  return OAuth2.createService('FirebaseCache')
    .setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
    .setTokenUrl('https://accounts.google.com/o/oauth2/token')
    .setPrivateKey(serviceAccountKey)
    .setIssuer(serviceAccountEmail)
    .setPropertyStore(scriptProperties)
    .setCache(CacheService.getScriptCache())
    .setScope([
      'https://www.googleapis.com/auth/userinfo.email',
      'https://www.googleapis.com/auth/firebase.database'
    ]);
}

实现代码以便从 Firebase 中读取和向其中写入数据

您将使用 Firebase Database REST API 对 Firebase 实时数据库执行读写操作。以下代码实现了访问该 API 所需的方法。

实现 getData()

无缓存的现有 getData() 代码的结构应大致如下所示:

firestore-cache/src/without-caching.js
/*
 * This file is only to demonstrate how the `getData()` fucntion would look
 * like without the Firebase Realtime Database caching. It is not a part of
 * the connector code and should not be included in Apps Script / Clasp.
 */

function getData(request) {
  var requestedFields = getFields().forIds(
    request.fields.map(function(field) {
      return field.name;
    })
  );

  var fetchedData = fetchAndParseData(request);
  var data = getFormattedData(fetchedData, requestedFields);

  return {
    schema: requestedFields.build(),
    rows: data
  };
}

要在您的 getData() 代码中使用缓存,请按以下步骤操作:

  1. 确定应缓存数据的“区块”或“单元”。
  2. 创建一个唯一键,将最小的数据单元存储在缓存中。
    对于示例实现,使用的是 configparams 中的 zipcode 用作键。
    可选:对于每位用户缓存,创建一个包含基本键和用户身份的复合键。实现示例:
    js var baseKey = getBaseKey(request); var userEmail = Session.getEffectiveUser().getEmail(); var hasheduserEmail = getHashedValue(userEmail); var compositeKey = baseKey + hasheduserEmail;

  3. 如果存在缓存数据,则检查缓存是否是最新的。
    在该示例中,特定邮政编码的缓存数据会与当前日期一同保存。从缓存检索数据时,缓存的日期为 对照当前日期进行检查。

    var cacheForZipcode = {
      data: <data being cached>,
      ymd: <current date in YYYYMMDD format>
    }
    
  4. 如果缓存数据不存在或不是最新的,则提取数据 并将其存储在缓存中

在以下示例中,main.js 包含具有缓存的 getData() 代码 。

示例代码

其他资源

Chrome 用户体验连接器为数千名用户打造了一个基于约 20 GB 的 BigQuery 表格的信息中心。此连接器将 Firebase Realtime Database 与 Apps 脚本缓存服务结合使用,提供了一种双层缓存方法。如需了解实现详情,请参阅代码