Metabase 数据类型与语义类型(Field Types)完全指南:从数据库元数据到智能可视化
Metabase 数据类型与语义类型Field Types完全指南从数据库元数据到智能可视化【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabaseMetabase 通过两套并行的列元数据体系——数据类型Data Type与语义类型Semantic Type又称 Field Type——来决定数据如何被格式化、哪些图表可用、过滤器如何工作以及 X-ray 等自动分析功能如何呈现结果。本文以 docs/data-modeling/semantic-types.md 为主线结合仓库中 Metabase 分层类型系统MHTS的实现源码完整讲解两类类型的区别、全部可选语义类型、Table Metadata 中的编辑与强制类型转换操作以及它们在后端如何驱动显示格式、图表推荐、字段值提取、字段过滤器与模型探索能力。读完本文你将能准确为列配置语义类型并理解这些配置在查询与可视化链路中的真实作用。两个概念Data Type 与 Semantic TypeMetabase 对每一列的元数据分两个层面描述二者职责不同、互相配合数据类型Data Type列在底层数据库中的原始类型例如Date或Text。Metabase 在数据库同步sync过程中读取并记录这些类型。语义类型Semantic Type也称 Field Type描述这一列数据应该被如何解读的标签。例如某列的数据类型是Text但存储的内容是邮箱地址那么给它打上Email语义类型后人和 Metabase都能知道这一列文本的用途。两者共同决定了 Metabase 的数据格式化方式、可用的图表类型、过滤器的行为以及众多其他功能。数据类型Data Types数据库原生类型的归一化Metabase 连接的数据库种类繁多PostgreSQL、MongoDB、BigQuery……为了统一处理它在底层维护了一套自有的类型层级体系将不同数据库的列类型归一到同一套分类下——这正是 src/metabase/types/core.cljc 中实现的Metabase Hierarchical Type SystemMHTS。例如PostgreSQL 的DATE和 MongoDB 的日期字段都会被归入 Metabase 的 Temporal 时间家族。主要数据类型如下Data Type示例数据库类型NumericINTEGER、FLOATTemporalDATE、TIMESTAMPTextVARCHAR、TEXTText-likeMongoDBBSONID、PostgresEnumBooleanBooleanCollectionJSON、BigQueryRECORD、MongoDBObject两个值得注意的限制与能力数组类型暂不支持。对于数组列你只能使用Is empty或Is not empty过滤器。对于部分字段你可以通过**强制类型转换cast**让 Metabase 将某一列按另一种数据类型解读例如把文本类型当日期类型用详见下文编辑数据类型与语义类型。源码视角MHTS 的分层继承在 src/metabase/types/core.cljc 中可以看到这套体系的实现思路每个类型通过derive从父类型继承形成一棵类型树。文档注释明确写道这是一个层级结构类型从一个或多个父类型派生父类型又派生自它们自己的父类型。这使得添加新类型时无需在前端或其他位置添加对应映射。例如某个数据库可以新增一个:type/CaseInsensitiveText只要让它从:type/Text派生其他地方都会自动把它当作文本处理。这套体系还区分了几类关键词Base Type / Effective Typebase type是列在数据仓库中的真实类型effective type是 Metabase 实际按哪种类型对待该列——当列应用了转换策略coercion strategy时二者不同。例如一个VARCHAR列base type :type/Text存储 ISO-8601 时间戳可以通过:Coercion/ISO8601-DateTime策略将 effective type 设为:type/DateTime。Semantic Type从:Semantic/*派生的类型表达列的业务含义如:type/UpdatedTimestamp。Relation Type与主键/外键相关的类型如:type/PK、:type/FK目前仍存储在semantic_type字段中。同时语义类型必须从允许它的数据类型派生。例如:type/UpdatedTimestamp从:type/DateTime派生因此只有 effective type 为日期时间的列才能设置该语义类型而布尔列不行——否则语义上就说不通。语义类型Semantic Types为列赋予含义语义类型为字段补充含义与上下文用于沟通字段用途并解锁额外功能。可选的语义类型取决于该列的数据类型。适用于任何字段的语义类型Entity key实体键标识该字段能唯一确定每一行例如 Product ID、序列号等。Foreign key外键指向另一张表中 Entity key 的字段用于连接不同表中相关联的数据。例如 Products 表里有一个 Customer ID 字段它指向 Customers 表中作为 Entity key 的 Customer ID。若要使用仪表盘联动过滤器linked filters必须先建立外键关系。在源码 src/metabase/lib/types/constants.cljc 中实体与外键被归入::entity分类semantic-type 指向:type/FK、:type/PK、:type/Name并分别定义了::foreign_key:type/FK与::primary_key:type/PK。前端/查询层通过 src/metabase/lib/types/isa.cljc 中的foreign-key?、primary-key?、entity-name?、id?等谓词来判断列的身份从而驱动联动过滤器、下钻drill-through等行为。数值字段Numeric的语义类型Quantity数量Score分数Percentage百分比Financial财务类Currency货币Discount折扣Income收入Location位置类Latitude纬度Longitude经度Category类别在 src/metabase/types/core.cljc 中可以看到这些语义类型均从对应数值类型派生:type/Quantity从:type/Integer派生:type/Share、:type/Percentage从浮点/十进制类型派生而:type/Currency是一个有趣的例子——它既从:type/Decimal派生表示真正的货币数据类型如 Postgresmoney也可以作为语义类型标记在普通DECIMAL列上:type/Income、:type/Discount、:type/Price、:type/Cost、:type/GrossMargin又都从:type/Currency派生。:type/Latitude、:type/Longitude则从:type/Coordinate派生:type/Coordinate同时从:type/Location与:type/Float派生。时间字段Temporal的语义类型Creation date创建日期Creation time创建时间Creation timestamp创建时间戳Joined date加入日期Joined time加入时间Joined timestamp加入时间戳Birthday生日对应源码中:type/CreationTimestamp、:type/CreationDate、:type/CreationTime都先派生自:type/CreationTemporal再分别派生自:type/DateTime、:type/Date、:type/TimeJoinTimestamp/JoinDate/JoinTime同理派生自:type/JoinTemporal。文本字段Text的语义类型Entity name实体名称Email邮箱URL网址Image URL图片网址Avatar URL头像网址Category类别Name姓名Title标题Description描述Product产品Source来源Location位置类City城市State州/省Country国家ZipCode邮编源码中:type/URL、:type/Email、:type/Name、:type/Title、:type/Description等均从:type/Text派生:type/ImageURL从:type/URL派生、:type/AvatarURL又从:type/ImageURL派生City/State/Country/ZipCode则构成:type/Address → :type/Location的派生链同时 City、State、Country 还被标记为:type/Category这会影响字段值缓存与同步见下文。集合字段Collection的语义类型Field containing JSON包含 JSON 的字段。详见《Working with JSON》。值得留意的是注释还提到被标记为:type/Category的语义类型字段在同步期间会被当作 category 字段处理即字段值FieldValues会被缓存并同步见metabase.analyze.classifiers.category/field-should-be-category?相关逻辑这正是下拉过滤器能拿到候选值的底层原因。编辑数据类型与语义类型管理员以及拥有管理表元数据权限的用户可以在Admin 后台的 Table Metadata 标签页中转换数据类型、编辑语义类型。转换数据类型Cast数据类型不能在 Metabase 中直接修改但你可以将某些数据类型转换为另一种类型例如让 Metabase 把一个文本类型列当作日期类型解读。转换只影响 Metabase 侧的解读方式不会改变数据库中该列的原始数据类型。根据 docs/data-modeling/metadata-editing.md 中的说明可选转换策略包括文本转日期时间ISO8601-Date、ISO8601-Datetime、ISO8601-Time数值转日期时间UNIXMicroSeconds-DateTime、UNIXMilliSeconds-DateTime、UNIXNanoSeconds-DateTime、UNIXSeconds-DateTime文本转数值String-Integer、String-Float其他Float-Integer、Datetime-Date典型场景数据库里有一个字符串类型的 Created At 列若想使用Created At 上周这类相对日期过滤器或把它用于 datetimeAdd 等表达式就可以先把它 Cast 成 Date 类型。如果 Metabase 没有你需要的转换策略可以通过 SQL 问题在查询中完成转换并保存为模型或在数据库中直接创建视图。需要补充的是Table Metadata 中的转换是全实例生效的如果只想在某个问题Question内临时转换可以在查询构建器中使用类型转换自定义表达式如date()或integer()把字符串转换为其他类型——这种转换仅作用于该查询。语义类型不会改变数据类型在表元数据设置中你可以选择一个与底层数据类型兼容的语义类型。语义类型只增加含义不应被当作类型转换工具。例如把一个文本字段的语义类型设为 QuantityMetabase 仍会把它当作文本字段处理。正确用法是借助语义类型告诉 Metabase 如何格式化或可视化该字段比如告诉它某个数值代表百分比。如果你希望调整某个列的全局显示名称例如把auth.user显示为 User、修改字段可见性Everywhere / Only in detail views / Do not include、设置过滤控件形态Search box / A list of all values / Plain input box、映射外键显示值或自定义数值映射都可以在同一套 Table Metadata 设置中完成详见表元数据编辑文档。数据类型与语义类型解锁的能力显示格式Display format部分语义类型会改变字段数据的展示方式。Table Metadata 中的格式设置全局生效但用户可以在单个图表中覆盖。语义类型格式效果Percentage以百分比显示例如0.75显示为75%Currency在图表和详情视图中数值前加上货币符号如$134.65。默认情况下表格视图只在表头显示货币符号但你可以修改元数据格式设置让每一行都显示该符号Latitude/Longitude以坐标形式显示如0.00000000° NEmail显示为mailto链接URL可格式化为可点击的链接Image URL可显示为图片见表格格式设置Avatar URL可显示为圆形头像图见表格格式设置包含 JSON 的字段在详情视图中以美化prettified格式显示 JSONEntity key / Foreign key在表格视图中高亮显示可视化推荐Automatic charts在查询构建器中创建问题并按某个字段Group by时Metabase 会根据该字段的数据类型与语义类型自动选择最合适的图表之后可以手动更换Group by 的数据类型自动图表Text/Category条形图Temporal折线图Numeric - 分箱binned条形图Numeric - 不分箱表格Boolean条形图无聚合表格如果使用了位置类语义类型还会有额外能力Group by 的语义类型功能Latitude/Longitude - 分箱网格地图Latitude/Longitude - 不分箱图钉地图Country世界区域地图State美国区域地图从列中提取值Extract values对部分字段你可以在表格视图的快捷操作或查询构建器的自定义表达式编辑器中快速提取列中的值数据类型可提取内容URL 语义类型host、domain、subdomain、pathEmail 语义类型host、domain时间数据类型月、日等日期组成部分X-rays自动透视分析当你对表、模型或实体执行 X-ray 时Metabase 会同时考虑数据类型与字段类型展示一系列总结该数据的图表。字段过滤器Field Filters理解字段类型对使用字段过滤器很有帮助——只有特定字段类型才能创建字段过滤器。JSON unfolding对于包含 JSON 的集合字段可参见《Working with JSON》了解 JSON 展开能力。源码视角isa?与字段分类上述自动选择图表判断是否可提取 URL 片段等能力在查询层面最终都收敛到 src/metabase/lib/types/isa.cljc 的isa?函数它同时检查列的effective-type或base-type与semantic-type是否属于目标类型。该文件还导出一系列语义谓词如email?、URL?、image-URL?、avatar-URL?、latitude?、longitude?、city?、country?、currency?、coordinate?等以及searchable?决定是否显示值搜索控件、summable?、category?等更宏观的分类。这套分类依据 src/metabase/lib/types/constants.cljc 中定义的type-hierarchies映射把前端友好的分类如::number、::temporal、::category、::coordinate映射到具体类型关键词上。自动推断语义类型同步与分类器语义类型除了手动设置Metabase 在数据库同步与指纹扫描阶段还会自动推断。仓库中的 src/metabase/analyze/classifiers/name.clj 就是一个基于字段名称与基础类型推断语义类型的分类器。它维护了一张[名称正则模式, 合法基础类型集合, 语义类型]的规则表从上到下依次匹配例如字段名正好是id→:type/PKlon/*_lon/*_longitude等且为浮点 →:type/Longitudelat/*_lat/*_latitude→:type/Latitudecity→:type/Citycountry*/*_country→:type/Country*_url/url→:type/URLfirst_name/full_name/last_name/name→:type/Namezip_code/postal_code→:type/ZipCode名称含discount→:type/Discount、含income→:type/Income、quantity/count/number→:type/Quantity名称含join且为日期/时间/时间戳 →:type/JoinDate/:type/JoinTime/:type/JoinTimestamp含create、start→ 对应 Creation 系列这也是为什么很多字段在初次同步后就有了合理的语义类型管理员只需在此基础上微调即可。在模型中设置语义类型让用户用查询构建器探索结果你可以为模型Model中的字段设置字段类型这能帮助 Metabase 理解 SQL 模型中的数据。如果你为 SQL 模型中的每一列都设置了类型用户就能用查询构建器和下钻drill-through菜单探索该模型的结果——这是让SQL 模型可被自助探索的关键一步。对于包含整型实体键integer entity keys的记录你还可以配置模型中的文本字段来在搜索结果中匹配该列以展示单条记录。进一步阅读表元数据编辑The Table Metadata page探索数据数据浏览器字段过滤器为 SQL 问题创建智能过滤组件数据库同步与扫描syncs and scans仪表盘联动过滤器字段格式化数据权限含管理表元数据权限理解数据类型与语义类型是让 Metabase 自动读懂你的数据、减少手工配置的关键。只需在 Table Metadata 中为关键列打上准确的语义标签格式化、图表推荐、过滤器、X-ray 与模型探索就会自动随之工作而本文介绍的源码实现类型层级、isa?判断、名称分类器则解释了这一切背后的统一机制。【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考