为了账号安全,请及时绑定邮箱和手机立即绑定

使用 Express 将 BigQuery 流式传输到前端

使用 Express 将 BigQuery 流式传输到前端

桃花长相依 2021-12-02 19:37:52
我正在尝试从BigQuery读取查询并将其流式传输到前端。在带有 Express 的 Node.js-land 中,这将是:app.get('/endpoint', (req, res) => {  bigQuery.createQueryStream(query).pipe(res);});但是,createQueryStream()它不会创建 Node.js 流,而是一个返回表行的自定义流对象,因此它失败了:(node:21236) UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_ARG_TYPE]: 第一个参数必须是字符串或缓冲区类型之一。接收类型对象这在官方文档中得到证实:bigquery.createQueryStream(query)  .on('data', function(row) {    // row is a result from your query.  })那么,有没有办法将 BigQuery 数据流式传输到前端?我想过两种可能的解决方案,但想知道是否有人知道更好的方法:JSON.stringify()行并返回JSONL而不是普通JSON。这增加了解码它的前端负担,但使双方都相当容易。转到REST API并使用以下请求进行实际流式传输:(request(url, { body: { query, params } }).pipe(res)或任何特定的 API,尚未在那里挖掘)。我很困惑,一个 Node.js 库说它可以进行流式处理,但它不适用于 Node.js 本机流,但情况似乎确实如此。
查看完整描述

2 回答

?
白衣非少年

TA贡献1155条经验 获得超0个赞

BigQuery 旨在与为不同编程语言编写的各种不同客户端库一起使用,因此,它不返回特定于 nodejs 的数据结构,而是返回大多数结构化编程语言通用的更通用的结构,例如作为对象。回答您的问题,是的,有一种方法可以将 BigQuery 数据流式传输到前端,但这是一个相当个人的选择,因为它所需要的只是从一种数据类型转换为另一种数据类型。但是,我想说最直接的方法是调用JSON.stringify(),您已经提到过。



查看完整回答
反对 回复 2021-12-02
?
跃然一笑

TA贡献1826条经验 获得超6个赞

我们最终制作了一个实现,将 BigQuery 的回复拼接到一个大的 JSON 数组中:


exports.stream = (query, params, res) => {

  // Light testing for descriptive errors in the parameters

  for (let key in params) {

    if (typeof params[key] === "number" && isNaN(params[key])) {

      throw new TypeError(`The parameter "${key}" should be a number`);

    }

  }


  return new Promise((resolve, reject) => {

    let prev = false;


    const onData = row => {

      try {

        // Only handle it when there's a row

        if (!row) return;


        // There was a previous row written before, so add a comma

        if (prev) {

          res.write(",");

        }

        res.write(stringify(row));

        prev = true;

      } catch (error) {

        console.error("Cannot parse row:", error);

        // Just ignore it, don't write this frame

      }

    };


    const onEnd = () => {

      res.write("]");

      res.end();

      resolve();

    };


    res.writeHead(200, { "Content-Type": "application/json" });

    res.write("[");

    bigQuery

      .createQueryStream({ query, params })

      .on("error", reject)

      .on("data", onData)

      .on("end", onEnd);

  });

};

它将通过拼接来构建一个大型 JSON 数组:


[   // <- First character sent

stringify(row1)   // <- First row

,   // <- add comma on second row iteration

stringify(row2)   // <- Second row

...

stringify(rowN)   // <- Last row

]   // <- Send the "]" character to close the array

这有以下优点:


数据在可用时立即发送,因此带宽需求较低。

(取决于 BigQuery 实现)服务器端的内存需求较低,因为并非所有数据都一次保存在内存中,只有小块。


查看完整回答
反对 回复 2021-12-02
  • 2 回答
  • 0 关注
  • 241 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信