搜索推荐数据.md 19.5 KB

1)BI 怎么设计(对标 Shopify/独立站“搜索/推荐”常见报表)

Shopify 的 Search & Discovery/行为报表里,搜索常看的就是 query、no results、no clicks、click rate、purchase rate(会话口径漏斗)。推荐系统的看板更强调 曝光→点击→加购→购买→收入,并按推荐位/算法/实验拆解。

1.1 搜索 BI(核心看板)

  • 搜索总览(KPI + 漏斗)

    • 搜索 PV/UV:search request 次数 / 搜索用户数
    • Click rate(会话口径,Shopify 常用):有点击的搜索会话 / 搜索会话
    • ATC rate:有加购的搜索会话 / 搜索会话
    • Purchase rate(会话口径,Shopify 常用):有购买的搜索会话 / 搜索会话
    • 结果曝光 CTR(结果口径):点击次数 / 结果曝光次数(更适合诊断排序/样式)
    • 延迟&稳定性:P50/P95 搜索耗时、错误率、空响应率
  • Query 分析(运营/选品/词库最常用)

    • 高热搜索词:按搜索 UV、曝光 UV、点击 UV、购买 UV 排序
    • 飙升词/新词:与过去 (7/14/28) 天对比的增速
    • 无结果 query(no results)
    • 有结果但无点击 query(no clicks)——强信号:相关性差/图片价位不吸引/首屏无货等
    • 建议词(suggestion):suggest 点击发起的搜索占比、suggest→点击/购买转化
  • 结果质量诊断(给算法/工程用)

    • 点击位置分布:position=1/2/3… 的点击占比(反推排序质量)
    • 类目/品牌/价格带分布:哪些 query 对哪些类目贡献转化
    • 筛选/排序使用率:filter 使用率、排序切换率、filter 后的 CTR/CVR 变化
  • 用户与渠道拆解(增长/产品用)

    • 新/老客、地域、语言、设备、来源(自然/广告/社媒)
    • 页面维度:首页搜索框 / 搜索页 / 分类页搜索 / 详情页内搜索等
  • Session/链路回放(你提到的 track_id/trace_id)

    • 单用户或单 trace:搜索→换词→曝光→点击→详情→加购→支付
    • 支持按 trace_id 串联一次“搜索请求”与后续行为(你们文档也强调这一点)

参考:Shopify 官方对搜索分析的核心指标包括 click rate、purchase rate、queries、no results、no clicks(见 Shopify Search & Discovery analytics)。

1.2 推荐 BI(核心看板)

  • 推荐位总览(按 placement/module)

    • Impressions/Clicks/CTR
    • ATC、Purchase、Revenue
    • Revenue per impression / per click
    • AOV(推荐归因订单)
    • 覆盖与多样性:覆盖商品数、长尾曝光占比、重复率(避免“只推爆款”)
  • 按算法/实验拆解

    • 算法版本(model_version/strategy_id)
    • 实验(experiment_id/variant_id)
    • Lift(增量):相对对照组的 CTR/CVR/Revenue uplift(最好有 holdout)
  • 健康度与风控

    • 缺货/下架命中率、被过滤原因分布(无库存/不可售/地域不发货)
    • 冷启动占比(新用户/新商品)与表现

2)数据层面的设计(埋点→数仓→指标→推荐特征)

你们已有统一事件骨架的方向(tenant_id / session_id / trace_id / event(oneof))。建议在数据层分成 ODS(原始)→DWD(清洗明细)→DWS(汇总)→ADS(看板语义层),同时给推荐做 离线+在线特征库

2.1 关键 ID 设计(决定 BI/推荐能否串起来)

  • tenant_id:多租户隔离必备(所有表分区/主键都带)
  • user_key:归一后的用户主键(优先 login/user_id;否则 anonymous_id/cookie_id)
  • session_id:会话(SDK 产生或用 30min inactivity 规则补齐)
  • trace_id(最重要):一次搜索/一次推荐刷新生成一个,后续点击/详情/加购尽量继承
  • request_id:后端请求日志关联(用于延迟、错误、召回/排序 debug)
  • order_id/cart_id/item_id(sku/spu):交易与商品归因

2.2 ODS:原始事件(“可回放、可重放”)

  • ods_ua_event_raw
    • tenant_id, event_time, received_time
    • identities(原始字段:distinct_id/login_id/anonymous_id/cookie_id…)
    • page/device/geo/referrer
    • trace_id, session_id, experiment 信息
    • event_name + properties(原始 JSON,保留全量)

你现在的 $pageview/$WebClick 自动采集能覆盖点击和页面,但 推荐/搜索“曝光”必须补埋点(否则 CTR、归因、训练样本都会缺)。

2.3 DWD:清洗后的事实表(BI/训练统一口径)

建议把“强分析对象”拆成事实表(便于 join、去重、做漏斗):

  • 搜索域

    • dwd_search_request:一次“搜索结果刷新/请求”的主表(强烈建议:每次请求一个 request_id,同时每次请求一个 trace_id
    • 用途:search PV/UV、零结果、延迟、query 聚合、会话口径漏斗分母(search_session)
    • 主键建议(tenant_id, request_id)
    • 核心索引建议
      • (tenant_id, created_at)
      • (tenant_id, user_key, created_at)
      • (tenant_id, query_normalized, created_at)
      • (tenant_id, trace_id)(用于 join 曝光/点击)
      • (tenant_id, search_session_id, created_at)
    • 字段建议(MySQL 参考类型,可按你们存储调整)
      • tenant_id VARCHAR(64) NOT NULL:店铺/租户
      • request_id VARCHAR(64) NOT NULL:该次搜索请求唯一 ID(前端生成或后端返回)
      • trace_id VARCHAR(64) NOT NULL:该次搜索链路 ID(一次结果集 = 一个 trace)
      • session_id VARCHAR(64) NULL:访问会话(30min inactivity)
      • search_session_id VARCHAR(64) NULL:搜索会话(一次“找东西”的连续过程)
      • user_id VARCHAR(64) NULL:登录用户 ID
      • anonymous_id VARCHAR(64) NULL:匿名用户(cookie 级稳定)
      • user_key VARCHAR(64) NOT NULL:归一用户主键(ETL 生成)
      • query TEXT NOT NULL:原始 query
      • query_normalized VARCHAR(512) NOT NULL:归一化 query(聚合用)
      • is_suggestion TINYINT NOT NULL DEFAULT 0:是否由 suggestion 触发
      • suggestion_text VARCHAR(512) NULL:命中的 suggestion(如有)
      • page_number INT NOT NULL DEFAULT 1:翻页页码(1-based)
      • sort VARCHAR(64) NULL:排序方式(如 relevance/price_asc/…)
      • filters_json JSON NULL:结构化筛选条件(原子字段更好;JSON 为起步方案)
      • filters_hash CHAR(32) NULL:filters 归一化后的 hash(便于聚合/去重)
      • results_count INT NOT NULL DEFAULT 0:总命中数
      • returned_count INT NULL:本页返回数量(page size)
      • latency_ms INT NULL:搜索耗时
      • is_zero_result TINYINT NOT NULL DEFAULT 0:是否零结果(可由 results_count=0 派生)
      • is_error TINYINT NOT NULL DEFAULT 0:是否错误
      • error_code VARCHAR(64) NULL:错误码(如超时/限流等)
      • page_type VARCHAR(64) NULL:发生搜索的页面(home/search/pdp/collection…)
      • referrer TEXT NULL:来源页
      • device_type VARCHAR(32) NULL:pc/mobile(可从 UA 解析)
      • country VARCHAR(8) NULL:国家(建议由 IP->Geo 派生;避免落全量 IP)
      • created_at DATETIME(3) NOT NULL:事件时间(毫秒级可选)
    • dwd_search_impression_item:搜索结果“曝光明细”(必须补,否则无法算 position CTR、训练负样本)
    • 用途:曝光 PV/UV、位置 CTR、召回/排序诊断、训练样本(曝光未点为负样本)
    • 主键建议(tenant_id, trace_id, item_id, position)(或 (tenant_id, request_id, item_id, position),二选一但全局统一)
    • 核心索引建议
      • (tenant_id, trace_id)
      • (tenant_id, request_id)
      • (tenant_id, item_id, exposed_at)
    • 字段建议
      • tenant_id VARCHAR(64) NOT NULL
      • request_id VARCHAR(64) NOT NULL
      • trace_id VARCHAR(64) NOT NULL
      • search_session_id VARCHAR(64) NULL
      • user_key VARCHAR(64) NOT NULL
      • query_normalized VARCHAR(512) NOT NULL
      • item_id VARCHAR(64) NOT NULL:spu 或 sku,需统一
      • position INT NOT NULL:在搜索结果中的排名(1-based)
      • score DOUBLE NULL:排序分(如 ES score/learning-to-rank score)
      • price DECIMAL(18,2) NULL:曝光时价格快照(可选但强烈建议)
      • currency VARCHAR(8) NULL
      • in_stock TINYINT NULL:曝光时库存可售快照(可选但强烈建议)
      • exposed_at DATETIME(3) NOT NULL:曝光时间
    • dwd_search_click_item:搜索结果点击明细(点击必须能回链到曝光/请求)
    • 用途:click UV、CTR(曝光口径/会话口径)、位置点击分布、归因触点
    • 主键建议(tenant_id, click_id)(若无 click_id,可用 (tenant_id, trace_id, item_id, clicked_at) 近似)
    • 核心索引建议
      • (tenant_id, trace_id)
      • (tenant_id, request_id)
      • (tenant_id, item_id, clicked_at)
    • 字段建议
      • tenant_id VARCHAR(64) NOT NULL
      • click_id VARCHAR(64) NULL:点击事件唯一 ID(推荐补)
      • request_id VARCHAR(64) NOT NULL
      • trace_id VARCHAR(64) NOT NULL
      • search_session_id VARCHAR(64) NULL
      • user_key VARCHAR(64) NOT NULL
      • query_normalized VARCHAR(512) NOT NULL
      • item_id VARCHAR(64) NOT NULL
      • position INT NULL:点击时该商品所在排名(无法取到则置空)
      • clicked_at DATETIME(3) NOT NULL
      • target_url TEXT NULL:点击跳转 URL(可选)
  • 推荐域

    • dwd_rec_request:一次推荐请求/刷新主表(一次刷新 = 一个 trace_id)
    • 用途:推荐 PV/UV、分推荐位指标、实验/版本拆解、延迟与稳定性
    • 主键建议(tenant_id, request_id)
    • 核心索引建议
      • (tenant_id, created_at)
      • (tenant_id, placement, created_at)
      • (tenant_id, trace_id)
      • (tenant_id, algo_id, model_version, created_at)
    • 字段建议
      • tenant_id VARCHAR(64) NOT NULL
      • request_id VARCHAR(64) NOT NULL
      • trace_id VARCHAR(64) NOT NULL
      • session_id VARCHAR(64) NULL
      • user_key VARCHAR(64) NOT NULL
      • placement VARCHAR(64) NOT NULL:推荐位(home/pdp/cart/checkout/search…)
      • module_id VARCHAR(128) NULL:页面内模块标识(一个页面多个推荐模块)
      • trigger_item_id VARCHAR(64) NULL:触发商品(PDP/Cart 场景常用)
      • candidates_count INT NULL:候选数量
      • returned_count INT NULL:返回条数
      • algo_id VARCHAR(64) NULL:策略/算法标识(rule/i2i/embedding/…)
      • model_version VARCHAR(64) NULL:模型版本
      • experiment_id VARCHAR(64) NULL:实验 ID(如有)
      • variant_id VARCHAR(64) NULL:分桶/分组(如有)
      • latency_ms INT NULL
      • is_error TINYINT NOT NULL DEFAULT 0
      • error_code VARCHAR(64) NULL
      • created_at DATETIME(3) NOT NULL
    • dwd_rec_impression_item:推荐曝光明细
    • 主键建议(tenant_id, trace_id, item_id, position)
    • 核心索引建议(tenant_id, trace_id)(tenant_id, item_id, exposed_at)
    • 字段建议
      • tenant_id VARCHAR(64) NOT NULL
      • request_id VARCHAR(64) NOT NULL
      • trace_id VARCHAR(64) NOT NULL
      • user_key VARCHAR(64) NOT NULL
      • placement VARCHAR(64) NOT NULL
      • module_id VARCHAR(128) NULL
      • trigger_item_id VARCHAR(64) NULL
      • item_id VARCHAR(64) NOT NULL
      • position INT NOT NULL
      • score DOUBLE NULL
      • price DECIMAL(18,2) NULL
      • currency VARCHAR(8) NULL
      • in_stock TINYINT NULL
      • exposed_at DATETIME(3) NOT NULL
    • dwd_rec_click_item:推荐点击明细
    • 主键建议(tenant_id, click_id)(或 (tenant_id, trace_id, item_id, clicked_at)
    • 核心索引建议(tenant_id, trace_id)(tenant_id, item_id, clicked_at)
    • 字段建议
      • tenant_id VARCHAR(64) NOT NULL
      • click_id VARCHAR(64) NULL
      • request_id VARCHAR(64) NOT NULL
      • trace_id VARCHAR(64) NOT NULL
      • user_key VARCHAR(64) NOT NULL
      • placement VARCHAR(64) NOT NULL
      • module_id VARCHAR(128) NULL
      • trigger_item_id VARCHAR(64) NULL
      • item_id VARCHAR(64) NOT NULL
      • position INT NULL
      • clicked_at DATETIME(3) NOT NULL
  • 转化域(全站通用)

    • dwd_view_item:商品详情页浏览(可承接 search/rec 的 trace,用于链路与兴趣序列)
    • 主键建议(tenant_id, view_id)(或 (tenant_id, user_key, item_id, viewed_at)
    • 核心索引建议(tenant_id, user_key, viewed_at)(tenant_id, item_id, viewed_at)
    • 字段建议
      • tenant_id VARCHAR(64) NOT NULL
      • view_id VARCHAR(64) NULL
      • session_id VARCHAR(64) NULL
      • user_key VARCHAR(64) NOT NULL
      • item_id VARCHAR(64) NOT NULL
      • source_type VARCHAR(32) NULL:来源(search/rec/direct/ads/…)
      • source_trace_id VARCHAR(64) NULL:来源 trace(若来自 search/rec)
      • dwell_time_ms INT NULL
      • viewed_at DATETIME(3) NOT NULL
    • dwd_add_to_cart:加购事实表(全站统一)
    • 主键建议(tenant_id, atc_id)(或 (tenant_id, user_key, item_id, added_at)
    • 核心索引建议(tenant_id, user_key, added_at)(tenant_id, item_id, added_at)
    • 字段建议
      • tenant_id VARCHAR(64) NOT NULL
      • atc_id VARCHAR(64) NULL
      • session_id VARCHAR(64) NULL
      • cart_id VARCHAR(64) NULL
      • user_key VARCHAR(64) NOT NULL
      • item_id VARCHAR(64) NOT NULL
      • quantity INT NOT NULL DEFAULT 1
      • price DECIMAL(18,2) NULL
      • currency VARCHAR(8) NULL
      • source_type VARCHAR(32) NULL:来源(search/rec/direct/…)
      • source_trace_id VARCHAR(64) NULL:来源 trace(若来自 search/rec)
      • added_at DATETIME(3) NOT NULL
      • cart_snapshot_json JSON NULL:购物车快照(可选,体积大时可下沉到独立表)
    • dwd_purchase:订单事实表(全站统一)
    • 主键建议(tenant_id, order_id)
    • 核心索引建议(tenant_id, user_key, paid_at)(tenant_id, paid_at)
    • 字段建议
      • tenant_id VARCHAR(64) NOT NULL
      • order_id VARCHAR(64) NOT NULL
      • user_key VARCHAR(64) NOT NULL
      • currency VARCHAR(8) NULL
      • total_amount DECIMAL(18,2) NULL
      • paid_at DATETIME(3) NOT NULL
    • dwd_purchase_item:订单明细事实表(全站统一)
    • 主键建议(tenant_id, order_id, item_id)(若一单同商品可多行,则增加 line_id
    • 核心索引建议(tenant_id, item_id, paid_at)(tenant_id, order_id)
    • 字段建议
      • tenant_id VARCHAR(64) NOT NULL
      • order_id VARCHAR(64) NOT NULL
      • line_id VARCHAR(64) NULL
      • user_key VARCHAR(64) NOT NULL
      • item_id VARCHAR(64) NOT NULL
      • quantity INT NOT NULL DEFAULT 1
      • price DECIMAL(18,2) NULL
      • paid_at DATETIME(3) NOT NULL
    • 落库/分区建议(MySQL)
    • 量小:按 tenant_id + created_at 索引即可
    • 量大:建议按月分表/分区(*_202601),或落到 ClickHouse/ES/湖仓;DWD 保持明细可追溯,DWS/ADS 做聚合提速
  • 归因桥(可选但强烈建议)

    • dwd_attribution_touch
    • order_id, item_id, last_touch_trace_id, touch_type(search/rec), touch_time, window(如 7d click/1d view)
    • 这样 BI 里的“搜索带来收入/推荐带来收入”不会口径混乱。

2.4 DWS/ADS:面向看板的汇总层(高性能)

  • dws_search_kpi_daily(tenant_id, date, page_type/device/geo/new_vs_returning…)
    • search_pv, search_uv, sessions_with_click, sessions_with_atc, sessions_with_purchase
    • click_rate_session, purchase_rate_session, zero_result_rate, no_click_rate, p95_latency
  • dws_query_daily(tenant_id, date, query_normalized)
    • searches, exposure_uv, click_uv, purchase_uv, zero_cnt, no_click_cnt
  • dws_rec_kpi_daily(tenant_id, date, placement, algo_id/model_version)
    • impressions, clicks, ctr, atc, purchases, revenue, rpi(revenue per impression)
  • dws_item_daily(tenant_id, date, item_id)
    • search_impr/click/atc/purchase、rec_impr/click/…(用于“商品天级统计特征”与运营)

3)推荐系统依赖的数据(“能训练、能实时、能解释”)

把特征分成 用户/商品/上下文,再分 静态/快照/统计/序列(实时)

3.1 用户基础信息(dim)

  • dim_user:user_key、注册时间、是否会员、国家/语言、获客渠道(如可得)、新老客标签
  • 合规:只存业务需要的最小信息,敏感字段做脱敏/哈希

3.2 用户实时特征(在线序列 + 聚合)

在线(Redis/Key-Value)建议保留:

  • 最近 N 次行为序列(按时间衰减)
    • view_item_seq(最近浏览商品)
    • search_query_seq(最近搜索词/类目)
    • click_seq(点击的商品,区分来自 search/rec)
    • cart_seq、purchase_seq
  • 实时聚合
    • 最近 1h/24h 搜索次数、点击次数、加购次数
    • 最近一次偏好类目/品牌/价格带(从序列实时计算)

离线(天/小时级)输出:

  • RFM、长期偏好向量(类目/品牌 embedding)、价格敏感度、复购周期等

3.3 商品基础特征(静态)

  • dim_item(sku/spu)
    • 类目、品牌、属性(颜色/尺码/材质…)、标题/描述、价格、币种、图片
    • 文本/图片 embedding(你们已有 embeddings 模块可复用)

3.4 商品快照(强业务约束,必须可回溯)

  • item_snapshot(tenant_id, item_id, snapshot_time)
    • 库存/可售、折扣、上新、发货国家限制、活动标签
  • 推荐/搜索曝光明细里最好写入当时的关键快照字段(至少 in_stock、price),避免事后回算失真。

3.5 商品天级统计特征(训练/排序最常用)

  • dws_item_daily 派生:
    • 1d/7d/28d:search_ctr、search_cvr、rec_ctr、rec_cvr、atc_rate、purchase_rate
    • 热度、趋势(环比/同比)、退货/取消(如可得)
    • 分 placement 的表现(同一商品在“购物车推荐”与“首页推荐”差异巨大)

3.6 标签(Label)与训练样本(建议一开始就定口径)

  • 曝光→点击(CTR)标签:以 impression_item 为样本
  • 点击→加购/购买(CVR/GMV)标签:以 click 或 impression 为样本,设定归因窗口
  • 负样本:同一 trace_id 下未被点击的曝光 item(更稳定)

4)你提到的两项“未完成工作”,数据层如何补齐

  • 商品曝光(搜索/推荐):必须新增 ExposureEvent(建议一屏/一次渲染批量上报 item 列表 + position + module/placement + trace_id)
  • 链路跟踪:以 trace_id 为主串联;若购买跨会话严重,可在 purchase 上补 attribution_trace_id 或单独落 attribution_touch 表做归因

如果你愿意,我可以基于你们现有 proto/事件骨架,把“搜索请求/曝光/点击/加购/购买/推荐请求”这几类事件的最小必填字段清单列成一张表(直接给前端埋点和后端 ETL 用),并给出每个指标(CTR/CVR/zero/no-click)的精确定义与 SQL 计算口径