3. 标准数据源解析

要把 GB 2760 做成一个可查询、可校验的应用,第一步不是写界面,而是把标准“拆开”。GB 2760 表面是一本厚厚的标准文本,实质上是一套由食品分类系统、添加剂品种名单和使用规定表三部分咬合而成的数据体系。查询应用的所有功能——按食品查可用添加剂、按添加剂查适用食品、判断某用量是否合规——都建立在对这三部分字段含义与数据关系的准确理解之上。本节就围绕“标准文本如何变成结构化数据”展开。

一、标准文本的三层结构

GB 2760 的正文通常包含:前言与范围、术语和定义、食品添加剂的使用原则、食品分类系统、食品添加剂的使用规定(以表格形式给出)、以及附录(如食品用香料名单、加工助剂名单等)。对数据建模而言,真正需要解析的是三层:

  • 食品分类层:用层级编码描述“这是什么食品”,如 01.0 乳及乳制品、01.01 巴氏杀菌乳、01.01.01 等更细的子类。分类号是查询的主键之一。
  • 添加剂品种层:每种添加剂有中文名、英文名、CNS 号、INS 号等标识,是“允许使用什么”的对象。
  • 使用规定层:把“某添加剂在某食品类别中的最大使用量、备注(如以残留量计、仅限某工艺)”记录下来,是三层之间的连接表。

这三层不是并列的,而是“食品分类树 + 添加剂字典 + 多对多规定表”的关系型结构。理解这一点,后面的字段设计就顺理成章。

二、食品分类系统:层级编码与继承规则

食品分类系统是一棵树,编码采用点分十进制,层级越深越具体。例如 01.0 是乳及乳制品,01.01 是乳(巴氏杀菌乳、灭菌乳等),01.01.01 可能是巴氏杀菌乳。查询时最关键的一条规则是“上位类规定对下位类有效,除非下位类另有规定”。也就是说,如果标准在 01.0 层面允许某添加剂使用,那么 01.01、01.01.01 原则上都适用;但若 01.01.01 单独列出了不同限量,则以更具体的规定为准。

这条继承规则直接决定了查询算法的写法:给定一个食品编码,不能只查完全相等的记录,而要沿编码路径向上回溯所有祖先节点,收集规定,再按“越具体越优先”的规则覆盖。很多查询应用出错,恰恰是只做了精确匹配,漏掉了上位类规定。

三、使用规定表的字段含义

使用规定表是数据量最大、字段最需要精确理解的部分。典型字段包括:

字段含义解析要点
食品分类号适用食品类别的编码需与分类树关联,支持祖先回溯
食品名称分类号对应的名称用于展示,避免只显示编码
添加剂名称品种中文名需与品种字典的 CNS 号对齐
最大使用量以 g/kg 计的限量注意单位,部分以“按生产需要适量使用”表述
备注残留量、工艺限制等常含“以…计”“仅限…”等条件,需结构化

其中“最大使用量”一栏有两种典型形态:数值型(如 0.5 g/kg)和文字型(“按生产需要适量使用”)。前者可直接比较,后者在查询时应标记为“无明确限量”,不能当作 0 或无穷大处理。备注字段则常出现“以苯甲酸计”“以残留量计”等表述,意味着实际检测值与限量值的比较基准不同,应用里应把这类条件单独抽出,作为提示信息展示,而不是塞进数值比较。

注意:同一添加剂在不同食品类别下的限量可能差异很大,甚至同一食品类别下因工艺不同而分列多条。解析时不能按“添加剂名称”去重合并,必须保留“食品分类号 + 添加剂 + 工艺条件”这一组合的完整性。

四、三层数据的关系与查询路径

把三层关系画清楚,查询逻辑就一目了然。下面的图展示了食品分类树、添加剂字典与使用规定表之间的连接方式,以及“按食品查添加剂”时的祖先回溯路径。

GB 2760 三层数据结构与“按食品查添加剂”路径 食品分类树 01.0 乳及乳制品 01.01 乳 01.01.01 巴氏杀菌乳 查询目标:01.01.01 回溯路径:自身 → 01.01 → 01.0 越具体越优先覆盖 编码点分十进制,层级即继承关系 使用规定表 食品分类号 + 添加剂 最大使用量 / 备注 数值型:0.5 g/kg 文字型:按生产需要适量 备注:以…计 / 仅限… 需单独结构化,不并入数值 组合键:分类号+添加剂+条件 不可按添加剂名称去重合并 添加剂品种字典 中文名 / 英文名 CNS 号 INS 号 品种唯一标识,供规定表引用 同一品种多名称需归一 回溯匹配 CNS 关联 查询结果 = 沿分类路径收集规定 → 按具体程度覆盖 → 关联品种字典输出名称与限量

图中红色虚线表示查询时的祖先回溯:从 01.01.01 出发,依次匹配自身、01.01、01.0 上的规定,再按“越具体越优先”合并。绿色实线表示规定表通过 CNS 号关联到品种字典,从而把编码翻译成用户看得懂的名称。这条路径就是查询应用的核心算法骨架。

五、解析实操:从文本到结构化记录

实际解析时,建议先把标准表格转成“一行一条规定”的扁平记录,再建立索引。以一条假设的示例记录说明字段落地方式(以下数值仅为教学示例,非标准原文):

{
  "food_code": "01.01.01",
  "food_name": "巴氏杀菌乳",
  "additive_cns": "17.001",
  "additive_name": "示例添加剂A",
  "max_use": 0.5,
  "unit": "g/kg",
  "limit_type": "numeric",
  "remark": "以残留量计",
  "remark_structured": { "basis": "residue" }
}

解析要点有三:其一,limit_type 区分数值型与“按生产需要适量使用”,后者不参与数值比较;其二,remark 原文保留,同时抽出 remark_structured 供程序判断比较基准;其三,food_code 必须保留完整层级,供回溯使用。完成扁平化后,再建立两张索引:以 food_code 为键的“食品→规定”索引,和以 additive_cns 为键的“添加剂→规定”索引,即可支撑双向查询。

校验小技巧:解析完成后,随机抽取若干食品编码,检查其祖先链上是否都能找到对应规定;若某编码在标准中确有规定却查不到,多半是分类号格式(如是否补零、点号位置)在解析时被改写了。

总结来说,GB 2760 的数据源解析本质是“一棵树 + 一本字典 + 一张多对多关系表”。把食品分类的继承规则、使用规定表的字段语义、以及备注中的比较基准这三件事处理准确,查询应用才不会在“查不到”或“限量判断错误”上翻车。后续的查询界面与合规判断,都只是在这套结构之上做展示与比较而已。