Google Sheets 按邮箱查询:查找匹配行
Google Sheets 按邮箱查询:通过 Webhook 接收邮箱地址,校验后在私有 Google Sheets 工作表中搜索,并返回首个匹配行。此模板使用标准工作流组件,无需 AI 模型。
状态:已于 2026年10月9日 在 AI Flowi Workflow 1.9.2 上完成生产环境测试(30 项用例全部通过)
作者:Ai Flowi · 发布于 · 更新于
任务
根据 email 列查找一行记录。实测行为:返回 HTTP 200,包含 found:true 和预先配置的行字段;或返回 HTTP 404,响应内容严格为 {"found":false}。匹配区分大小写,不去除首尾空白,也不转换为小写。
适用对象
适用于通过可信后端查询小型私有电子表格中内部记录的团队。访问个人数据前,必须验证调用方是否获得授权;仅持有 API 密钥,并不意味着有权查看任意邮箱对应的行记录。
输入示例
{"email":"lookup@example.com"}
发送 JSON 时,使用 Content-Type: application/json 和私有的 x-api-key 请求头。所有示例均使用虚构数据。
设置
- 授权你的 Google 连接,并创建私有测试工作表。将第 1 行依次设置为
email,name,status,note,列标题须全部小写且互不重复。添加虚构的测试数据行。 - 添加下列八个节点。在 Universal Webhook 中选择 POST、Platform API Key,并将 POST 响应模式设为 From Flow。将其 Production Endpoint 复制到可信的请求发送端。
- 在 Search Row 中选择已授权的 Google Account、私有的 Spreadsheet ID 和 Sheet Name。将 Key Column 设为
email,Header Row 设为1,并启用 Case Sensitive Key Match。 - 在每个 JSON Operations 中选择 JQ Expression,并保持查询字段可见。粘贴下方的查询表达式,严格按照表格连接对应端口。
- 在两个 Webhook Response 节点中,将默认 HTTP Status 设为 200 OK,Content Type 设为
application/json,Additional Response Headers 设为Cache-Control: no-store。连接到 Response Definition 的数据会将默认状态码覆盖为 200、404 或 422。 - 处理私有记录前,先使用虚构测试数据执行完整检查清单。每次请求前后都要比较整个工作表。
| 节点 ID | 组件 | 用途 |
|---|---|---|
| Webhook-lookup | Universal Webhook | 接收请求 |
| JSON-validate | JSON Operations | 校验邮箱地址 |
| Router-valid | Verification Router | 按校验结果分流 |
| JSON-key | JSON Operations | 准备搜索键 |
| SearchRow-lookup | Search Row | 读取首个匹配行 |
| JSON-response | JSON Operations | 提取响应正文和状态码 |
| Response-result | Webhook Response | 返回查询结果 |
| Response-reject | Webhook Response | 返回校验错误 |
节点连接与字段映射
下列内部端口名称与配置指南一致。多个 JSON Operations 和 Webhook Response 节点分别使用不同的 ID。
| 源节点.output | 目标节点.input |
|---|---|
Webhook-lookup.request_data | JSON-validate.data |
JSON-validate.data_output | Router-valid.verification_result |
Router-valid.verified | JSON-key.data |
JSON-key.data_output | SearchRow-lookup.row_data |
SearchRow-lookup.result | JSON-response.data |
JSON-response.data_output | Response-result.response_definition |
Router-valid.rejected | Response-reject.response_definition |
校验:JSON-validate
def reject: {verified:false, status_code:422, body:{error:"Invalid email", code:"INVALID_EMAIL"}};
.body as $b
| if ($b|type) != "object" then reject
elif ($b.email|type) != "string" then reject
elif ($b.email|length) < 1 or ($b.email|length) > 254 then reject
elif ($b.email|test("^[^@[:space:]]+@[^@[:space:]]+[.][^@[:space:]]+$")) then {verified:true, email:$b.email}
else reject end
搜索键:JSON-key
{email:.email}
只有通过校验的邮箱地址才会传入 Search Row 的 Search Data(row_data)。电子表格、工作表和响应字段均为固定配置,调用方无法覆盖这些设置。
响应:JSON-response
if .found == true then
if (.row|type) != "object" then error("Unexpected lookup result")
else {status_code:200, body:{found:true, row:{email:.row.email, name:.row.name, status:.row.status, note:.row.note}}} end
elif .found == false then {status_code:404, body:{found:false}}
else error("Unexpected lookup result") end
连接到 Response Definition,不要连接到 Response Body。数值类型的 status_code 决定 HTTP 状态码;body 提供 JSON 正文。这样可从已完成的查询响应中移除原始工作表 ID、连接值、行号和 Google 元数据。
相关内容:Google Sheets 定时写入:每天记录状态行。
已脱敏的请求与响应示例
以下是使用虚构数据进行生产环境测试时的实测响应,不包含真实端点或凭据。
POST https://workflow.aiflowi.com/api/v1/webhook/<your-flow-id>
Content-Type: application/json
x-api-key: <your-private-key>
{"email":"lookup@example.com"}
实测匹配成功:HTTP 200。
{"found":true,"row":{"email":"lookup@example.com","name":"Synthetic First","status":"active","note":"first row"}}
实测未找到 absent@example.com 对应记录:HTTP 404。
{"found":false}
实测拒绝 {}:HTTP 422。
{"error":"Invalid email","code":"INVALID_EMAIL"}
校验与失败行为
请求正文必须是对象。邮箱地址必须是长度为 1–254 个字符的字符串,且包含一个 @,域名中须有点号,且不得包含空白字符。空值、非文本值和格式错误的地址均会在读取工作表前被拒绝。额外字段会被忽略。这项实用校验不验证邮箱能否接收邮件,也不验证邮箱归属。
缺少 API 密钥或密钥无效时,实测返回 HTTP 403。格式错误的 JSON 返回 HTTP 422,并包含文档所示的 INVALID_EMAIL 对象。工作流内生成的响应具有 JSON 内容类型和 Cache-Control: no-store;平台生成的 403 响应具有 JSON 内容类型,但不含 no-store 响应头。
Search Row 读取整个工作表,并选择标题行下方按实际行顺序出现的首个匹配行。已有的重复记录保持不变。行末缺失的 note 值会变为 JSON null.
此工作流图不会捕获 Google 错误。 访问权限、列标题、配额或电子表格错误都可能中止执行,并返回原始平台错误,状态码可能是 HTTP 404 或 500。这种响应不同于工作流中受控的 404 {"found":false}。它可能包含私有工作表元数据,并绕过已配置的响应头。对外提供结果前,请先验证配置,并在可信后端处理错误。
测试结果
30 次按顺序执行的生产环境请求全部通过。每次请求后,全部五个数据行及其值均保持不变。已确认临时 API 密钥被删除。非对象正文组和无效邮箱值组各包含五次请求。
| 用例 | 条件 | 预期响应 | 实测 HTTP 状态码 | 实测工作表变化 | 结论 |
|---|---|---|---|---|---|
| T1 | 有效地址匹配成功 | 200; {"found":true,"row":{"email":"lookup@example.com","name":"Synthetic First","status":"active","note":"first row"}} | 200 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T2 | 缺少 email | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T3 | email 为数值 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T4 | JSON 格式错误 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T5 | 缺少密钥 | 403; 平台定义的响应正文 | 403 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T6 | 密钥无效 | 403; 平台定义的响应正文 | 403 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T7 | 地址格式错误 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T8 | 无匹配行 | 404; {"found":false} | 404 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T9 | 大小写不同 | 404; {"found":false} | 404 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T10 | 重复记录:按实际行顺序取首行 | 200; {"found":true,"row":{"email":"duplicate@example.com","name":"Synthetic Duplicate First","status":"active","note":"earliest match"}} | 200 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T11 | 行末单元格为空 | 200; {"found":true,"row":{"email":"blank@example.com","name":"Synthetic Blank","status":"active","note":null}} | 200 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T12 | 首尾含空白字符 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T13-0 | 正文不是对象 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T13-1 | 正文不是对象 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T13-2 | 正文不是对象 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T13-3 | 正文不是对象 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T13-4 | 正文不是对象 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T14-0 | email 值无效 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T14-1 | email 值无效 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T14-2 | email 值无效 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T14-3 | email 值无效 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T14-4 | email 值无效 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T15 | 254 个字符的地址 | 404; {"found":false} | 404 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T16 | 255 个字符的地址 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T17 | 忽略调用方提供的配置 | 200; {"found":true,"row":{"email":"lookup@example.com","name":"Synthetic First","status":"active","note":"first row"}} | 200 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T18 | 重复读取 | 200; {"found":true,"row":{"email":"lookup@example.com","name":"Synthetic First","status":"active","note":"first row"}} | 200 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T19 | 第二组不同的测试数据 | 200; {"found":true,"row":{"email":"other@example.com","name":"Synthetic Other","status":"inactive","note":"other row"}} | 200 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T20 | 含两个 @ 符号 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T21 | 域名不含点号 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
| T22 | 内含换行符 | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 个数据行;所有值不变 | 通过 |
下载
下载不含凭据的配置指南,查看节点设置、JQ 表达式和端口。它是 设置指南,并非可导入的工作流文件.
可导入的工作流下载:暂不提供;尚未测试导入后的副本。完成实际构建、凭据审查和导入副本测试后,可以添加已脱敏的导入文件。在此之前,请按照文档自行搭建节点与映射。
必需配置
- 一个 AI Flowi Workflow 工作区,以及供请求发送端使用的私有 Platform API Key。
- 一个已授权且有权访问私有电子表格的 Google 连接。
- 你自己的私有 Spreadsheet ID 和已配置的查询工作表;不要使用调用方提供的标识符。
- 第 1 行使用全部小写且互不重复的
email,name,status,note列标题。如需使用其他数据结构,请有意识地调整响应中提取的字段。 - 用于检查匹配成功、无匹配、大小写差异、重复记录和空单元格的虚构测试数据行;以及用于验证调用方授权的可信后端。
测试版本与日期
已于 2026年10月9日(MYT)在 AI Flowi Workflow 1.9.2 上完成生产环境测试。本次证据未测量运行时节点计费情况,也未验证导入后的副本。
| 字段 | 值 |
|---|---|
| 测试部署版本 | AI Flowi Workflow 1.9.2 |
| 生产环境测试日期 | 2026年10月9日 (MYT) |
| 实际节点运行次数 | 未测量;仅有基于工作流结构的估算 |
| 导入副本测试 | 所提供的证据中未执行此项测试 |
用量与费用假设
套餐:Go 年付方案每月 USD8 起(月付 USD10),Plus 年付方案每月 USD16 起(月付 USD20),Pro 100 年付方案每月 USD80 起(月付 USD100),Pro 200 年付方案每月 USD160 起(月付 USD200),Pro 500 年付方案每月 USD400 起(月付 USD500),每月包含 5,000 至 250,000 个 Flowi Tokens,并支持充值;每次节点运行消耗 1 个 token;不包含第三方 API 和模型使用费用。
按所走路径估算:有效查询(包括无匹配结果)运行 7 个节点;校验拒绝运行 4 个节点;平台拒绝密钥时,工作流图中的节点运行次数为 0。这些估算基于工作流结构,仍需运行时证据验证。工作表查询失败时,已有四个节点完成运行,并尝试了一次失败的搜索;失败节点如何计费尚未验证。
| 请求数 | 全部为有效查询 | 全部因校验失败被拒绝 | 全部因密钥问题被拒绝 |
|---|---|---|---|
| 100 | 700 Flowi Tokens | 400 Flowi Tokens | 0 次工作流图运行 |
| 1,000 | 7,000 Flowi Tokens | 4,000 Flowi Tokens | 0 次工作流图运行 |
| 10,000 | 70,000 Flowi Tokens | 40,000 Flowi Tokens | 0 次工作流图运行 |
对于混合请求,按 7 × valid + 4 × invalid 估算。每次重试都会再次执行所走的路径。测试套件的估算包括 139 次预期 Webhook 节点运行,以及 31 次各运行一个节点的回读:若所有请求均无需重试即可完成,预期消耗 170 个 Flowi Tokens。获取组件目录、保存工作流图和轮询事件不属于节点运行。
无需模型组件或第三方付费 API。套餐不包含第三方 API/模型的使用费用。仍需遵守 Google 账号访问权限和 API 配额限制。此处不假定任何 Token 超额用量价格或额外套餐权益。
限制
- 读取整个工作表并进行线性搜索,不适合作为高流量数据库索引。
- 精确且区分大小写的键匹配可能无法匹配大小写不同或首尾带空格的工作表值。有重复记录时取首个匹配行;外部并发编辑可能改变结果。
- 列标题和返回的单元格值必须符合已配置的数据结构。公式与格式化值遵循 Google API 的默认行为。
- 此工作流图不提供逐邮箱授权、Google 错误恢复或快照隔离。
- 值比较不验证公式、格式、权限或其他工作表。生产环境的 HTTP 状态码、响应正文和值检查已通过;导入副本验证仍未测试。
后续步骤
使用你自己的私有配置重新执行检查清单。检查密钥清理和原始错误处理,然后对导入副本进行脱敏并重新测试;完成这些步骤后,才能将下载文件视为已通过生产环境测试。
相关文档:Universal Webhook · Google 连接 · Webhook 到 Google Sheets 教程 · 使用场景.