如何根据用户输入参数从 BigQuery 获取结果

Posted

技术标签:

【中文标题】如何根据用户输入参数从 BigQuery 获取结果【英文标题】:How to get result from BigQuery based on user input parameters 【发布时间】:2020-08-27 04:18:46 【问题描述】:

这是我之前的帖子的延续,用于制作带有 url 参数的 api,将其传递给 BigQuery,如果 luid 记录在 orderid 列中有数据,则返回 True 。 How to check whether data exists in specific column on BigQuery with Flask?

我更改了 sql,似乎这个 sql 在 GCP 控制台上运行良好,但如您所见,如果您从浏览器输入正确的参数,它会返回 Flase('f0_': 0))。我需要修复这个 sql 吗??

[URL:https://test-989898.df.r.appspot.com?luid=U77777]
The output of return str(row)
↓
Row((True,), 'f0_': 0)


The output of SQL with same luid above on console 
↓
row | f0_
1   | true 


SELECT EXISTS(SELECT 1
FROM `test-266110.conversion_log.conversion_log_2020*` as p
WHERE luid = "U77777" AND orderid != '' limit 1000)

我尝试了这篇文章,如下所示。用户输入参数在 BigQuery 中不可用?? https://cloud.google.com/bigquery/docs/parameterized-queries

@app.route('/')
def get_request():
    luid = request.args.get('luid') or ''
    client = bigquery.Client()
    query = """SELECT EXISTS(SELECT 1
FROM `test-266110.conversion_log.conversion_log_2020*` as p
WHERE @luid = p.luid AND orderid != '' limit 1000)"""
    job_config = bigquery.QueryJobConfig(
    query_parameters=[
        bigquery.ScalarQueryParameter("luid", "STRING", luid),
    ]
    )
    query_job = client.query(query, job_config=job_config)
    query_res = query_job.result()
    for row in query_res:
        return str(row)


↓
Row((True,), 'f0_': 0)

我在这个问题上已经有一段时间了,欢迎提出任何想法。谁有好的解决方案??

from flask import Flask, request, jsonify
from google.cloud import bigquery


app = Flask(__name__)


@app.route('/')
def get_request():
    luid = request.args.get('luid') or ''
    client = bigquery.Client()
    query = """SELECT EXISTS(SELECT 1
FROM `test-266110.conversion_log.conversion_log_2020*` as p
WHERE @luid = p.luid AND orderid != '' limit 1000)"""

    job_config = bigquery.QueryJobConfig(
    query_parameters=[
        bigquery.ScalarQueryParameter("luid", "STRING", luid),
    ]
    )
    query_job = client.query(query, job_config=job_config)
    query_res = query_job.result()
    #  first_row = next(iter(query_job.result()))
    for row in query_res:
        return str(row)
        #return jsonify(luid:query_res.total_rows)
    """
    if query_res == :
        return jsonify(luid: str(True))
    else:
        return jsonify(luid: str(False))
    """
if __name__ == "__main__":
    app.run()



↓
Row((True,), 'f0_': 0)

【问题讨论】:

【参考方案1】:

您似乎已经解决了大部分问题,这只是让它们一起工作的问题。下面是一个可以帮助解决 BigQuery 问题的快速示例,并展示了使用公共数据集表编写查询模式的不同方式。

from google.cloud import bigquery
client = bigquery.Client()

# assume you get this from your flask app's param.  this is the "luid" you're checking.
value = "treason"
# rewriting the sql demonstrate a similar thing with a public dataset table
sql = "SELECT COUNTIF(word=@luid AND corpus='sonnets') > 0 as word_is_sonnet FROM `bigquery-public-data.samples.shakespeare`"

config = bigquery.QueryJobConfig(
    query_parameters=[
        bigquery.ScalarQueryParameter("luid", "STRING", value),
    ]
)

job = client.query(sql, job_config=config)

# this is a bit odd, but in this case we know we're dealing with a single row
# coming from the iterable based on the query structure.
first_row = next(iter(job.result()))
print(first_row.get("word_is_sonnet"))

不过,我要确保您了解 BigQuery 的工作原理和查询费用。您似乎正在对一系列表(原始查询中的通配符表)进行点查找,这意味着您可能会进行大量表扫描以满足此请求。

我只是想指出这一点,因此如果您的意图是发出许多这样的请求,您不会对性能或成本感到惊讶。

【讨论】:

非常感谢。我想确认这个重写 sql 只是示例,所以不能按我的预期工作,对吧?? 是的,在公共数据集表上演示更容易。 我明白了。谢谢你。我通过检查 GCP 控制台上的 SQL 执行历史记录找到了问题的原因。我的 sql 中的变量似乎没有传输到 BigQuery,所以我需要寻找在我的 sql 上设置动态变量的方法。

以上是关于如何根据用户输入参数从 BigQuery 获取结果的主要内容,如果未能解决你的问题,请参考以下文章

如何从 BigQuery 中的 Firebase 事件中获取用户表?

如何安全地为 bigquery 节点插入转义用户输入?可以在 bigquery.insert 节点库上使用参数化查询吗?

如何获取 ValueProvider 的值并将其写入 BigQuery 表?

从 node.js 获取 bigquery 结果到浏览器

如何获取参数化 BigQuery 查询的控制台视图?

如何授予查看者从 Data Studio 更改 BigQuery 参数的权限