有点晚的答案,但这可能会帮助其他面临同样问题的人。
附加到图表的小部件/搜索过滤器会发出自己的 getData 调用。如果您的自定义适配器被构建为通过来自第三方服务的 API 调用来检索数据,这些数据与由 GDS 转发的 request.fields 属性无关 => 那么这些 API 调用乘以 N+1(其中 N =您的报告正在实施的小部件/搜索过滤器)。
我也找不到官方的解决方案,所以我发明了一种使用缓存的解决方法。
图表对 getData 的请求(通常请求比搜索过滤器更多的字段)将是唯一允许查询 API 端点的请求。在开始这样做之前,它将在缓存“cache_{hashOfReportParameters}_building”=> true 中存储一个键。
if (enableCache) {
cache.putString("cache_{hashOfReportParameters}_building", 'true');
Logger.log("Cache is being built...");
}
它将检索 API 响应、分页并缓冲结果。
一旦完成,它将删除缓存键“cache_{hashOfReportParameters} building”,并将缓存到目前为止缓冲在“cache {hashOfReportParameters}_final”中的最终合并结果。
当涉及到过滤器时,它们也会调用:getData,但通常最多只有 3 个请求的字段。我们要做的第一件事是确保它们不能在主 getData 调用之前开始执行......所以我们为可能是相同数据集之后的搜索过滤器/小部件添加一点延迟:
if (enableCache) {
var countRequestedFields = requestedFields.asArray().length;
Logger.log("Total Requested fields: " + countRequestedFields);
if (countRequestedFields <= 3) {
Logger.log('This seams to be a search filters.');
Utilities.sleep(1000);
}
}
之后,我们计算报告所有移动部分的哈希值(日期范围,加上您设置的所有其他参数,这些参数可能会影响从 API 端点检索到的数据):
现在最好的部分是,只要主图仍在构建缓存,我们就让这些 getData 调用等待:
while (cache.getString('cache_{hashOfReportParameters}_building') === 'true') {
Logger.log('A similar request is already executing, please wait...');
Utilities.sleep(2000);
}
在这个循环之后,我们尝试检索“cache_{hashOfReportParameters}_final”的内容——如果我们失败了,有一个备份计划总是一个好主意——允许它再次遍历 API。我们在检索缓存的数据时遇到了大约 2% 的错误率......
使用缓存的结果(或缓冲的 API 响应),您只需根据 GDS 需要的模式转换您的响应(这在图和过滤器之间有所不同)。
当您开始实现此功能时,您会注意到另一个问题...... Google 缓存限制为每个密钥最大 100KB。但是,您可以缓存的键的数量没有限制......幸运的是,其他人过去也遇到过类似的需求,并提出了一种智能解决方案,将您需要缓存的一大块拆分为多个缓存键,然后粘合当需要检索时,它们会重新组合成一个对象。
见:https ://github.com/lwbuck01/GASs/blob/b5885e34335d531e00f8d45be4205980d91d976a/EnhancedCacheService/EnhancedCache.gs
我无法与您分享我们实施的最终解决方案,因为它对客户来说太具体了——但我希望这至少能让您对如何解决问题有一个好主意。
如果近实时足以满足您的需求,缓存完整的 API 结果通常是一个好主意,可以避免无缘无故的往返和服务器负载。