Appearance
数据模型
一张主表 + 七张关联表 + 一组参考字典。 各局原始数据在字段名、状态口径、编号规则上差异极大,入库时统一到这一套结构,跨局查询不需要写 if office == ... 的分支。
表关系总览
ref_office · ref_status_dict · ref_nice_class · ref_event_type · ref_deadline_rule
↑ 枚举与字典:全站共用一份,API 的 /v1/offices、/v1/status-codes 直接读它们
tm_trademark ──┬── tm_class 尼斯分类明细(一条商标 N 行)
(主表) ├── tm_goods_service 商品/服务文本
├── tm_event 生命周期事件(按月/年分区,5300 万行)
├── tm_owner_rel ─ tm_owner 权利人及关联关系
├── tm_right 权利记录(注册、续展、质押、许可)
├── tm_case 案件(异议、撤销、无效、诉讼)
└── tm_ir_designation 马德里指定领地展开主表 tm_trademark 74 列,下面按"你在什么时候会用到它"分组,只列对外返回的字段。
一、身份:怎么唯一确定一条记录
| 字段 | 类型 | 说明 |
|---|---|---|
public_id | varchar(26) | 对外主键,格式 {局代码}-{20 位大写 HEX},例 TW-EE0233AE265A98F448F0 |
office_code | varchar(8) | 法域代码:TW FR EM AU GB SG SE NO HK WO ES |
office_record_id | varchar(64) | 各局自己的登记号或内部 ID,用来回官方系统对齐 |
id | bigint | 内部自增主键,只在同一次响应内稳定,不要存 |
public_id 跨局唯一、不含业务含义、不会因为注册号变更而变,可以放心当缓存键和 URL 路径。
二、标识:商标本身长什么样
| 字段 | 类型 | 说明 |
|---|---|---|
mark_text | text | 商标文字,多语原文,不做翻译(法语、瑞典语、繁体照原样) |
mark_text_norm | text | 检索用归一化文本:大小写折叠、全半角、去标点空白 |
mark_lang | varchar(8) | 原文语种,如 fr sv zh-Hant |
mark_type | varchar(32) | word / figurative / combined / 3d / sound … |
mark_transliteration | text | 音译(如日文假名、韩文罗马字) |
mark_translation | text | 官方提供的译文,不是我们翻的 |
mark_image_url | text | 图样外链(指向该局官方地址) |
image_path | text | 图样本地缓存路径,image_status 记录采集状态 |
phash | bigint | 图样感知哈希,用于以图搜图(二期能力) |
series_no / series_count | smallint | 系列商标的第几条 / 共几条 |
mark_text_all | text | 系列商标的全部文字合并 |
我们不翻译
mark_text。要中文语义请用mark_translation(官方译文)或自己过一遍模型——这是我们刻意保留原文的原因:商标的近似判断对字形字音极度敏感,机翻会毁掉证据链。
三、分类:尼斯与维也纳
| 字段 | 类型 | 说明 |
|---|---|---|
nice_classes | smallint[] | 尼斯分类数组,一条商标多类时一次返回 |
vienna_codes | varchar(16)[] | 维也纳图形分类,仅图样商标有 |
class_count | smallint | 类数(冗余,用于快速筛选) |
gs_count | int | 商品服务条目数 |
中国台湾的旧制分类:1994 年以前申请的案件用的是旧制分类,入库时统一 旧制号 + 1000 存入 nice_classes。所以看到 1001 及以上,表示"旧制 N 类"(N = 值 - 1000),不是尼斯第 1001 类。前端展示时需要单独标注,按尼斯过滤时要排除。
四、状态:四轴模型
| 字段 | 类型 | 说明 |
|---|---|---|
status_primary | varchar(16) | 只有三个值:active / pending / dead |
status_stage | varchar(32) | 细分阶段,23 个取值,如 registered expired refused |
status_reason | varchar(32) | 走到该状态的原因,12 个字典值 |
status_challenges | varchar(32)[] | 当前面临的挑战(异议、撤销、无效等),可多个 |
status_raw | text | 各局原始状态原文,永远保留 |
status_date | date | 状态最后变更日期 |
完整取值、各局映射、事件码说明见 状态体系。
五、日期
| 字段 | 说明 |
|---|---|
filing_date | 申请日 |
priority_date | 优先权日 |
registration_date | 注册日 |
publication_date | 公告日 |
opposition_end_date | 异议期截止日 |
expiry_date | 专用权届满日 |
renewal_due_date | 应续展日 |
⚠️ 两处口径差异要知道:
renewal_due_date≠expiry_date。中国台湾的续展制是"到期前 6 个月起可续展",我们把renewal_due_date落成应续展日、并非失效日,且对应事件affects_status=false(不改变法律状态)。- 中国台湾有 270 万件
expiry_date落在未来且状态仍为active——这是正常的,别当成脏数据。
六、权利人
| 字段 | 说明 |
|---|---|
owner_name | 权利人名称原文 |
owner_country | 国别(ISO 3166-1 alpha-2) |
owner_name_norm | 归一化名称,用于跨局同名合并 |
单条商标只带第一权利人。完整权利人列表、转让链、关联关系走 tm_owner_rel → tm_owner,通过 /v1/trademarks/{id}/owners 取。
七、溯源四件套
这是数据产品的底线——每一行都能回到官方原始记录:
| 字段 | 说明 |
|---|---|
source | 数据来源标识,如 tipo-opendata / wipo-madrid-daily / hk-gazette |
source_version | 批次版本,如 20261016 |
raw_id | 指向 raw_payload 表,存该条记录的原始报文 |
fetched_at | 抓取时间 |
office_url | 官方详情页 URL,点开就是原页面 |
json
{
"public_id": "TW-EE0233AE265A98F448F0",
"office_code": "TW",
"office_record_id": "02559720",
"office_url": "https://cloud.tipo.gov.tw/S282/S282WV1/...",
"source": "tipo-opendata",
"source_version": "20261016",
"fetched_at": "2026-10-16T02:31:07Z"
}八、派生与质量字段
| 字段 | 说明 |
|---|---|
data_quality | smallint 0–100,字段完整度打分(分类/图样/权利人/日期各占权重) |
risk_level / risk_score | 风险等级与分值(冲突数量、被异议次数、近似商标密度) |
conflict_count | 同局同类的在先近似商标数量 |
image_status | 图样采集状态:pending / ok / failed / absent |
detail_status | 详情页补采状态 |
phash_tries | 图样哈希重试次数(-1 表示永久失败,不再重试) |
deleted_at | 软删标记,所有查询默认过滤 deleted_at IS NULL |
九、事件表 tm_event
5300 万行,按年份分区(13 个分区,legacy 覆盖 1880–2016,之后每年一个,future 兜底)。
| 字段 | 说明 |
|---|---|
tm_id | 关联 tm_trademark.id |
event_code | 归一化事件码,字典在 ref_event_type(311 个) |
event_date | 事件发生日 |
title | 事件标题(官方原文 or 官方中文) |
description | 事件详情 |
from_status / to_status | 该事件导致的状态迁移 |
office_raw | 官方原始事件文本 |
source / raw_id | 同主表溯源 |
唯一键 (tm_id, event_code, event_date, COALESCE(office_raw,''))——同一商标同一天可能有多条不同事件,靠 office_raw 区分。
十、一条真实的完整记录
GET /v1/trademarks/TW-EE0233AE265A98F448F0 返回(有删减):
json
{
"public_id": "TW-EE0233AE265A98F448F0",
"office_code": "TW",
"office_record_id": "02559720",
"application_number": "115890016",
"registration_number": "02559720",
"mark_text": "CaraQ",
"mark_text_norm": "caraq",
"mark_type": "word",
"nice_classes": [9, 35, 38, 41, 42],
"class_count": 5,
"status": {
"primary": "active",
"stage": "registered",
"reason": null,
"challenges": [],
"raw": "註冊",
"date": "2026-09-01"
},
"filing_date": "2026-03-11",
"registration_date": "2026-09-01",
"expiry_date": "2036-09-01",
"owner_name": "卡拉科技有限公司",
"owner_country": "TW",
"data_quality": 86,
"office_url": "https://cloud.tipo.gov.tw/S282/S282WV1/...",
"source": "tipo-opendata",
"fetched_at": "2026-10-16T02:31:07Z"
}已知限制
这些是真实缺口,我们不藏
- 图样覆盖不均:中国台湾 98.5%、新加坡 99%、中国香港 97%;但欧盟、英国、法国为 0%(三局未采集图样),澳大利亚 32%、瑞典 36%。
GET /v1/offices的image_coverage字段是准确值。 - 商品服务文本:法国仅 28% 有明细(源数据只给类别不给全文)。
- 中国香港存量:仅覆盖 2016 年 7 月之后的公报(34.3 万件),之前号段(300–303)拿不到。
- 瑞典数据停更:源站
opendata.prv.se最后更新 2025-05-21,之后无新增。 - 中国台湾
status_reason尚未映射:约 140 万条仍是 TIPO 原始单字母码(6A2…),status_primary/status_stage不受影响,只影响原因细分。 - 马德里(WO)是"一标多国":同一条 IR 上某些缔约国驳回、某些给保护、某些无效是常态,会同时存在
granted与surrendered事件——这不是数据错误。