Поиск строки в Google Sheets по email
Поиск строки в Google Sheets по email: получите адрес электронной почты через вебхук, проверьте его, выполните поиск на закрытом листе Google Sheets и верните первую совпавшую строку. Этот шаблон использует стандартные компоненты рабочего процесса без модели ИИ.
Статус: проверено в рабочей среде 9 октября 2026 года на AI Flowi Workflow 1.9.2 (пройдены 30 из 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 и оставьте поле query видимым. Вставьте приведённые ниже запросы. Соедините именно те порты, которые указаны в таблице.
- В обоих узлах Webhook Response задайте HTTP Status по умолчанию 200 OK, Content Type —
application/json, а Additional Response Headers —Cache-Control: no-store. Подключённый Response Definition заменяет статус по умолчанию на 200, 404 или 422. - Перед обработкой закрытых записей выполните все проверки на искусственных тестовых данных. Сравнивайте весь лист до и после каждого запроса.
| Идентификатор узла | Компонент | Назначение |
|---|---|---|
| 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 имеют разные идентификаторы.
| Исходный узел.выход | Целевой узел.вход |
|---|---|
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 Data (row_data) узла Search Row передаётся только проверенный адрес электронной почты. Таблица, лист и поля ответа заданы в настройках; вызывающая сторона не может их переопределить.
Ответ: 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. Так из ответов завершённого поиска исключаются исходные идентификаторы таблиц, значения подключения, номера строк и метаданные 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 | адрес электронной почты отсутствует | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 строк данных; все значения без изменений | ПРОЙДЕНО |
| T3 | число вместо адреса электронной почты | 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 | некорректное значение адреса электронной почты | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 строк данных; все значения без изменений | ПРОЙДЕНО |
| T14-1 | некорректное значение адреса электронной почты | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 строк данных; все значения без изменений | ПРОЙДЕНО |
| T14-2 | некорректное значение адреса электронной почты | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 строк данных; все значения без изменений | ПРОЙДЕНО |
| T14-3 | некорректное значение адреса электронной почты | 422; {"error":"Invalid email","code":"INVALID_EMAIL"} | 422 | 5 -> 5 строк данных; все значения без изменений | ПРОЙДЕНО |
| T14-4 | некорректное значение адреса электронной почты | 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 и настроенный лист для поиска; не используйте идентификаторы, переданные вызывающей стороной.
- Уникальные заголовки
email,name,status,noteв нижнем регистре в строке 1. Если нужна другая схема данных, целенаправленно измените набор полей ответа. - Строки с искусственными данными для проверки совпадения, отсутствия совпадения, различия в регистре, дубликатов и пустых ячеек; доверенный сервер для проверки прав вызывающей стороны.
Проверенная версия и дата
Проверено в рабочей среде на AI Flowi Workflow 1.9.2 9 октября 2026 года (MYT). Представленные результаты не включают измерение фактического списания токенов за выполнение узлов и проверку импортированной копии.
| Поле | Значение |
|---|---|
| Проверенная версия развёртывания | AI Flowi Workflow 1.9.2 |
| Дата проверки в рабочей среде | 9 октября 2026 года (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 токен за каждый запуск узла; использование сторонних 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. Каждая повторная попытка заново выполняет выбранную ветку. Оценка для набора тестов добавляет 31 запуск одного узла для контрольного чтения к 139 ожидаемым запускам узлов вебхука: итого 170 Flowi Tokens, если каждый запрос завершается без повторных попыток. Получение каталога, сохранение схемы и опрос событий не являются запусками узлов.
Компонент модели и платный сторонний API не требуются. Использование сторонних API и моделей не входит в тариф. Требования к доступу через аккаунт Google и квоты API сохраняются. Расчёт не предполагает конкретной цены токенов сверх лимита или дополнительных возможностей тарифа.
Ограничения
- Чтение всего листа и линейный поиск; схема не подходит в качестве индекса базы данных для большого объёма запросов.
- Точное сопоставление ключей с учётом регистра может не найти значения с другим регистром или пробелами по краям. Выбирается первый дубликат; одновременные внешние изменения могут повлиять на результат.
- Заголовки и возвращаемые значения ячеек должны соответствовать настроенной схеме данных. Для формул и форматированных значений используются настройки Google API по умолчанию.
- Эта схема не обеспечивает проверку прав для каждого адреса электронной почты, восстановление после ошибок Google или изоляцию на уровне снимка данных.
- Сравнение значений не проверяет формулы, форматирование, права доступа или другие листы. Проверки HTTP, тела ответа и значений в рабочей среде пройдены; импортированная копия ещё не проверена.
Следующие шаги
Повторите все проверки с собственными настройками закрытого доступа. Проверьте удаление ключей и обработку ошибок платформы, возвращаемых без фильтрации, затем удалите конфиденциальные данные из импортированной копии и повторно протестируйте её, прежде чем считать скачиваемый файл проверенным в рабочей среде.
По теме: Universal Webhook · подключение Google · Руководство по передаче данных из вебхука в Google Sheets · Сценарии использования.