106 lines
3.9 KiB
Markdown
106 lines
3.9 KiB
Markdown
# Phase 5: 数据管道优化 — 技术研究
|
||
|
||
**研究日期:** 2026-03-21
|
||
**阶段目标:** 入库去重可靠(30天窗口)、公司清洗流程顺畅、公司招聘信息写入 ClickHouse
|
||
|
||
---
|
||
|
||
## 1. 现状分析
|
||
|
||
### 1.1 DATA-01:30 天窗口去重
|
||
|
||
**位置:** `app/services/ingest/dedup.py` — `batch_dedup_filter()`
|
||
|
||
**现状(有缺口):**
|
||
|
||
```sql
|
||
-- 当前去重 SQL(无时间窗口)
|
||
SELECT job_id FROM job_data.boss_job WHERE job_id IN {keys}
|
||
```
|
||
|
||
**缺口:** 查的是全量历史数据,同一职位 30 天内只入库一次的语义没有实现。
|
||
理论上 ClickHouse 表可能有几年的旧数据,老 job_id 永远不会重新入库。
|
||
|
||
**正确逻辑:** 查询条件加 `AND created_at > now() - INTERVAL 30 DAY`,
|
||
只在近 30 天内去重,超过 30 天的同一职位可以重新入库。
|
||
|
||
**修复范围:** `batch_dedup_filter()` 的两个 SQL 查询各加一行 WHERE 条件。
|
||
|
||
---
|
||
|
||
### 1.2 DATA-02:统一入库管道(spiderJobs 推送)
|
||
|
||
**位置:** `app/services/ingest/service.py`(已有 IngestService.store_batch)
|
||
|
||
**现状(有缺口):**
|
||
- 后端 `cleaning.py`、`company_jobs_sync.py` 已通过 `IngestService.store_batch()` 入库 ✅
|
||
- 外部脚本 `spiderJobs/` 是独立运行的,它们通过 HTTP 推送到服务端 API
|
||
- 服务端 API 接收推送数据后应该走 `IngestService`,需要确认 API 路由是否已经接入
|
||
|
||
**需确认:** 查看 `app/api/v1/` 里 spiderJobs 推送的接收端点,确认是否走 IngestService。
|
||
|
||
**设计决策:**
|
||
- spiderJobs 推送的应该是原始 JSON 数据
|
||
- 接收端点 → IngestService.store_batch() → ClickHouse
|
||
- 来源字段(channel/platform)在 IngestService 中已经记录
|
||
|
||
---
|
||
|
||
### 1.3 DATA-03:公司清洗定时任务
|
||
|
||
**位置:** `app/services/company_cleaner.py`(335行)
|
||
|
||
**现状(基本完整):**
|
||
|
||
全链路已实现:
|
||
1. `collect_pending_companies()`: ClickHouse 查 30 天内有招聘的公司 ID ✅
|
||
2. `process_pending_companies()`: 遍历 MySQL 清洗队列 → 爬公司详情 → 写 MySQL ✅
|
||
- 用 `asyncio.to_thread(boss/qcwy/zhilian_service.get_company_detail)` ✅
|
||
3. 同步写 company_jobs:调用 `company_jobs_sync.sync_company_jobs()` ✅
|
||
4. `cleanup_old_records()`: 清理已处理记录 ✅
|
||
|
||
**缺口:** 日志链路需确认 `logger.info` 是否结构化(已使用 loguru ✅)
|
||
|
||
**结论:** DATA-03 已基本完成,无需大改。
|
||
|
||
---
|
||
|
||
### 1.4 DATA-04:公司招聘信息写入 ClickHouse
|
||
|
||
**位置:** `app/services/company_jobs_sync.py`
|
||
|
||
**现状(部分完成):**
|
||
|
||
```python
|
||
# 当前用 "mini" channel 和 "job" data_type 存公司职位
|
||
store_result = await router.store_batch(source, "mini", "job", jobs)
|
||
```
|
||
|
||
**缺口:** 公司职位(company_jobs)和普通搜索职位(search_jobs)使用同一个注册配置,
|
||
无法区分来源,且 ClickHouse 表(boss_job/qcwy_job/zhilian_job)混入了不同来源。
|
||
|
||
**方案:**
|
||
- 新增 channel = "company"(区分公司关联职位 vs 搜索职位)
|
||
- 在 `ingest/configs/boss.py` 等添加 `channel="company"` 的额外配置
|
||
- 或者保持现有 channel="mini",但 ClickHouse 表层面通过 `channel` 列区分
|
||
|
||
**决策(保守方案):**
|
||
- 现有表已有 `channel` 列,`company_jobs_sync.py` 改用 `channel="company"` 调用
|
||
- 无需新建表,无 ClickHouse DDL 变更
|
||
- 只需在 registry 补注册 `channel="company"` 的配置条目
|
||
|
||
---
|
||
|
||
## 2. 需确认:spiderJobs 推送接收端点
|
||
|
||
需要查看 `app/api/v1/` 是否有专门接收 spiderJobs 推送数据的端点,
|
||
以及该端点是否已经调用了 IngestService。
|
||
|
||
---
|
||
|
||
## 3. 计划分解
|
||
|
||
- **Plan 01(DATA-01):** 修改 `dedup.py` 的两个查询 SQL 加 30 天窗口条件(+新增 mock 测试)
|
||
- **Plan 02(DATA-02 + DATA-04):** 确认/修复推送 API 端点 + registry 补注册 `channel="company"` + company_jobs_sync 改用 `channel="company"`
|
||
- **(DATA-03 已完成,无需单独计划)**
|