办公文档
需要把外部 CSV/JSONL 按…
适用于将外部表格或 JSONL 数据按自然键回写到 HubSpot CRM,并逐条处理成功/失败的场景。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
需要把外部 CSV/JSONL 按 em特定
解决思路
- 先阅读 `bulk-operations/SKILL.md`,复用其中的 JSONL 管道、`--dry-run`/digest、history 与限流规范;本技能是在其上做按自然键 upsert 的工作流。
- 核心动作是用 `hubspot objects upsert --type X --id-property <natural-key>`:从 stdin 读 JSONL,按属性键(联系人用 `email`,公司用 `domain`)逐条创建或更新,每条记录一次 CLI 调用;不要循环 `search` → 空? → `create`。
- 输入每行格式:`{"id":"jane@example.com","properties":{"firstname":"Jane","jobtitle":"VP"}}`。
- 输出每行格式:成功为 `{"id":"123","ok":true,"data":{...,"new":true|false}}`,失败为 `{"ok":false,"error":{...}}`;顺序与输入一致。
- 用 `jq` 将 CSV/JSONL 重塑为目标 JSONL,先用 `--dry-run` 预览,再执行。
- 自然键始终小写——CRM 匹配是精确匹配。
- 用 `hubspot properties list --type contacts` 确认可用属性名;不要硬编码属性列表。
- 参考 `bulk-operations/resources/json-patterns.md` 获取重塑惯用法。
- CSV → JSONL 示例:`csvjson external.csv | jq -c '.[]' > external.jsonl`。
- 预览示例:`cat external.jsonl | jq -c '{id:(.email|ascii_downcase), properties:{firstname:.first, lastname:.last, jobtitle:.title, company:.company}}' | hubspot objects upsert --type contacts --id-property email --dry-run | head`。
- 执行示例(同一管道去掉 `--dry-run`,捕获结果):`cat external.jsonl | jq -c '{id:(.email|ascii_downcase), properties:{firstname:.first, lastname:.last, jobtitle:.title, company:.company}}' | hubspot objects upsert --type contacts --id-property email | tee /tmp/upsert.results.jsonl`。
- 公司处理:换成 `--type companies --id-property domain`,并用 `.domain|ascii_downcase` 重塑为 `id`。
- 处理逐条成功/错误输出:用 `jq` 拆分 `ok`/`failed`,检查失败模式,修复输入后只重试失败项。
- 拆分命令:`jq -c 'select(.ok==true)' /tmp/upsert.results.jsonl > /tmp/upsert.ok.jsonl`;`jq -c 'select(.ok==false)' /tmp/upsert.results.jsonl > /tmp/upsert.failed.jsonl`;`jq -r '.error.status' /tmp/upsert.failed.jsonl | sort | uniq -c`;`jq -r '.data.new' /tmp/upsert.ok.jsonl | sort | uniq -c`。
- 遇到 429:拆分输入并分更小的块重跑(见 `bulk-operations` 限流说明)。
- 遇到 400:通常是属性名错误或枚举值无效——修正重塑逻辑后重跑失败输入。
- `upsert` 本身非破坏性,但写回可能覆盖已有字段;始终先 `--dry-run` 并抽查。
- 对批量删除或覆盖已有数据,遵循 `bulk-operations/SKILL.md` 的 dry-run → digest → confirm 流程。
- 恢复:`hubspot history --since 1h`。
- 只读取匹配(不回写),或自然键不是 CRM 属性时,用 OR-search → update:重复 `--filter` 标志,每个标志是一组 OR。
- 已验证上限:每次调用 5 个 OR 组;6+ 会返回 `400 too many filterGroups (count: N, max allowed: 5)`,按 5 个一组切分。
- OR-search 示例:`xargs -n5 < emails.txt | while read -r e1 e2 e3 e4 e5; do args=(); for e in "$e1" "$e2" "$e3" "$e4" "$e5"; do [ -n "$e" ] && args+=(--filter "email=$e"); done; hubspot objects search --type contacts "${args[@]}" --properties email,firstname,company; done > /tmp/matches.jsonl`。
- 更新示例:`jq -c '{id, properties:{lifecyclestage:"marketingqualifiedlead"}}' /tmp/matches.jsonl | hubspot objects update --type contacts --dry-run`。
- 更大规模的键控 enrichment 优先用 `upsert`——一条管道,避免分块计算。
适用边界 · 注意事项
- 只想读取匹配、不回写,或自然键不是 CRM 属性时,不要用 upsert,改用重复 `--filter` 的 OR-search → update。
- 需要批量删除或覆盖已有数据时,不要直接 upsert,先遵循 `bulk-operations/SKILL.md` 的 dry-run → digest → confirm 流程。
- 没有 HubSpot CLI/CRM,或未读 `bulk-operations/SKILL.md` 的限流/干跑规范时,不要按本技能执行。