0860eed92b
store_mapping 的语义是"一次比价(一个 trace)= 一个真实店铺一行", 各目标平台解析出自己的 shopId 就往同一行填自己那几列: 淘宝腿先建行(id_taobao/name_taobao), 将来京东腿解析出 id 再合并进同一行(id_jd/name_jd)。trace_id 唯一约束天然就是这一行的合并键。 原 insert 是"撞 trace 就跳过", 第二条腿来上报会被丢掉, 撑不起渐进填充。改成 upsert: - 不存在 → INSERT(同原行为) - 已存在 → 填空合并(fill-the-blanks): 只写该行当前为 NULL 的列, 绝不覆盖已有非空值。 保证后到平台只填自己的列、动不了先到平台的数据; 共享列(geo/source/溯源)先到先得。 - 并发撞唯一约束 → 回滚后转走同一填空合并路径(不依赖 ON CONFLICT, PG/SQLite 都安全)。 返回值 (created, row_id): created=1 新建 / 0 合并; 端点日志区分"新建/合并"并带上 jd 列。 注: 一行里 id_taobao 与 id_jd 共存只是 name-match 置信度(两腿搜同一源店名各自匹配到某店), 非已核实同一实体; 作 append-only 原始资产留存, 精确匹配下游做。 验证: TestClient 打真实 PG —— 淘宝建行(inserted=1) → 京东同 trace 合并(只 UPDATE id_jd/ name_jd, geohash 不进 SET) → 淘宝重报不同 id 不覆盖(无 UPDATE)。最终一行各列正确, 已清理。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
51 lines
1.4 KiB
Python
51 lines
1.4 KiB
Python
"""平台店铺映射内部上报的收发模型。
|
|
|
|
pricebot 在淘宝比价拿到 shopId 后 server→server POST 一行映射。所有字段可空(按比价
|
|
角色稀疏填充),server 端只校验共享密钥 + 幂等(trace_id)落库。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from pydantic import BaseModel
|
|
|
|
|
|
class StoreMappingIn(BaseModel):
|
|
"""一次比价的跨平台店铺映射上报体(一行)。"""
|
|
|
|
trace_id: str
|
|
business_type: str = "food"
|
|
source_platform: str | None = None
|
|
|
|
# 跨平台身份(按角色稀疏填充)
|
|
id_taobao: str | None = None
|
|
name_taobao: str | None = None
|
|
id_meituan: str | None = None
|
|
name_meituan: str | None = None
|
|
id_jd: str | None = None
|
|
name_jd: str | None = None
|
|
|
|
# 地理
|
|
city: str | None = None
|
|
geohash: str | None = None
|
|
lng: float | None = None
|
|
lat: float | None = None
|
|
taobao_address: str | None = None
|
|
|
|
# 溯源
|
|
source_device_id: str | None = None
|
|
source_user_id: int | None = None
|
|
|
|
# 淘宝原料(可复跳 / 可重解析 / 调试)
|
|
taobao_share_url: str | None = None
|
|
taobao_resolved_url: str | None = None
|
|
taobao_deeplink: str | None = None
|
|
|
|
attrs: dict | None = None
|
|
|
|
|
|
class StoreMappingOut(BaseModel):
|
|
"""上报结果。inserted=1 为新建该 trace 行,0 为合并进已存在行(填空,不覆盖);
|
|
row_id 为该 trace 对应行 id。"""
|
|
|
|
inserted: int
|
|
row_id: int | None = None
|