ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

DataHub 搜索文档(Search Document)建模指南:从 PDL 模式定义到搜索索引与 API

DataHub 搜索文档(Search Document)建模指南:从 PDL 模式定义到搜索索引与 API DataHub 搜索文档Search Document建模指南从 PDL 模式定义到搜索索引与 API【免费下载链接】datahubThe Context Platform for your Data and AI Stack项目地址: https://gitcode.com/GitHub_Trending/da/datahub导读本文深入讲解 DataHub 元数据模型中的核心概念——搜索文档Search Document它如何在 PDLPegasus Data Language 中显式建模如何从各类元数据 Aspect 派生字段以及它如何驱动搜索 API 的过滤、排序与摘要snippet生成。读完本文你将掌握 Search Document 与 Entity、Relationship 的区别、字段建模的关键规则URN、软删除、数组字段、跨实体派生字段并理解其在 Elasticsearch 索引构建与查询链路上的底层实现。什么是搜索文档在 DataHub 中搜索文档Search Document是用于支撑搜索能力的核心数据模型它同样使用 PDL 显式定义。从建模角度看Document 与 Entity 和 Relationship 模型非常相似每个属性attribute/字段field都包含一个从各类元数据 Aspect 中派生出来的值。但与 Entity 模型相比Search Document 有一个关键差异搜索文档允许拥有数组类型array的属性且该数组只能包含原始类型primitive或枚举enum项。这一限制的根源在于底层全文检索引擎的能力模型大多数全文检索引擎如 Elasticsearch支持对数组字段做成员资格测试membership testing——例如一个包含文档中全部词项的数组字段可以用于terms过滤查询。因此将多值信息建模为数组字段是 Search Document 区别于实体元数据模型的重要特性。搜索文档与实体、关系模型的对照维度EntityRelationshipSearch Document建模语言PDLPDLPDL值来源元数据 Aspect元数据 Aspect元数据 Aspect可跨实体派生数组字段一般不可含纯 primitive/enum 数组支持 URN 数组允许 primitive/enum 数组支持成员测试存储位置图数据库Neo4j图数据库Neo4j独立搜索索引Elasticsearch用途实体状态表示实体间关联过滤、排序、摘要生成从存储角度看Graph 中保存的是实体与关系的当前状态视图而每个 Search Document 类型或 Entity 类型会被映射到 Elasticsearch 中的一个独立搜索索引详见 搜索索引Search Index。搜索文档的两大核心用途文档属性最直接的应用是执行搜索过滤filtering例如找出所有「名或姓与 Joe 相似且汇报给userFoo」的User。这类查询需要把firstName、lastName、management等字段都建模进 Search Document才能让搜索引擎按条件过滤。由于Search Document 同时也是搜索 API 的主要接口main interface其属性还可以用于格式化搜索摘要search snippet——即搜索结果列表中展示的命中片段。因此一个自然的倾向是能加多少属性就加多少属性。这在 DataHub 中是被接受的因为底层检索引擎本身就是为索引大量字段而设计的。不过需要注意的是字段并非越多越好——过多的字段会带来索引膨胀与构建开销实际建模时建议围绕可过滤、可排序、可展示摘要三类需求来取舍。PDL 建模示例BaseDocument 与 UserDocument下面给出User搜索文档的完整 PDL 模式示例与 search-document.md 中一致。建模时需要注意以下五点每个搜索文档必须包含一个类型特定的urn字段它一般映射到 Graph 中的一个实体与Entity类似每个文档有一个可选的removed字段用于软删除soft deletion与Entity类似其余所有字段都声明为optional以支持部分更新partial updatemanagement展示了字符串数组字段的写法ownedDatasets展示了跨实体派生字段的写法——该字段的值来源于与其他类型实体此处为Dataset关联的元数据 Aspect。首先定义所有文档共用的公共字段namespace com.linkedin.metadata.search /** * Common fields that may apply to all documents */ record BaseDocument { /** Whether the entity has been removed or not */ removed: optional boolean false }接着定义User的搜索文档namespace com.linkedin.metadata.search import com.linkedin.common.CorpuserUrn import com.linkedin.common.DatasetUrn /** * Data model for user entity search */ record UserDocument includes BaseDocument { /** Urn for the user */ urn: CorpuserUrn /** First name of the user */ firstName: optional string /** Last name of the user */ lastName: optional string /** The chain of management all the way to CEO */ management: optional array[CorpuserUrn] [] /** Code for the cost center */ costCenter: optional int /** The list of dataset the user owns */ ownedDatasets: optional array[DatasetUrn] [] }字段设计要点逐项拆解urn必填文档主键直接对应 URN 规范 中urn:Namespace:Entity Type:ID的实体标识。在 SearchEntity.pdl 中搜索 API 返回的每条结果同样以entity: Urn作为核心字段。removed可选默认false软删除标记。搜索索引不需要物理删除文档通过该字段即可在查询时排除已移除的实体这也与索引始终可以基于历史 MCL 重建的设计保持一致详见 graph.md。optional字段这是支持**部分更新partial update**的关键。当某个 Aspect 发生变化时Index Builder 只需更新文档中受影响字段而不必重写整个文档。数组字段management、ownedDatasets数组项必须为 primitive 或 enumURN 本质上是字符串同样满足要求。数组字段天然支持搜索引擎的成员资格测试例如过滤出属于某条管理链的所有用户。跨实体派生字段ownedDatasets字段值可以来自其他类型实体Dataset的 Ownership 等 AspectIndex Builder 会监听相关实体/方面的变更并联动更新本文档。从搜索文档到搜索索引GMA 的索引能力每个 Search Document 类型或 Entity 类型在 Elasticsearch 中都有独立、对立的搜索索引。除标准检索引擎能力分析器 analyzer、分词器 tokenizer、过滤查询、分面 faceting、分片 sharding 等之外GMA 还额外支持三项与 Search Document 直接相关的特性见 search-index.md索引文档的部分更新Partial update与 PDL 中大量optional字段的设计呼应——仅当相关 Aspect 变更时才局部改写文档字段避免整文档重写。多值字段的成员资格测试Membership testing正是数组字段存在的意义支撑terms类过滤查询。索引间零停机切换Zero downtime switchIndex Builder 逻辑变更时系统会创建新版本索引并从历史 MCL 回放填充填充完成后通过 GMS 的简单配置切换即可上线且随时可回滚到旧版本索引。搜索查询的抽象层则由Search DAO提供可参考 metadata-serving.md 中的说明。底层实现SearchDocumentTransformer 与索引构建从 Aspect 到文档字段的提取在仓库的metadata-io模块中SearchDocumentTransformer.java 负责将实体快照snapshot中的 Aspect 提取为文档字段。从源码结构看SearchDocumentTransformer.java它接收三个关键上限参数maxArrayLength数组字段的最大长度——提取时会对数组执行截断subList(0, Math.min(fieldValues.size(), maxArrayLength))见 SearchDocumentTransformer.java防止单个数组字段过度膨胀maxObjectKeys嵌套对象的最大键数同样有截断逻辑见 SearchDocumentTransformer.javamaxValueLength单个字段值的最大长度参与FieldExtractor.extractFields的取值见 SearchDocumentTransformer.java。字段提取基于实体注册表中的searchableFieldSpecs/searchScoreFieldSpecs/searchableRefFieldSpecs定义即哪些 Aspect 字段可以进入搜索文档、哪些参与打分由元数据模型注册时声明。索引构建工厂与配置项在metadata-service的 ElasticSearchIndexBuilderFactory.java 中ES 索引构建器ESIndexBuilder通过 Spring 配置注入以下索引级参数配置键application.yml前缀作用elasticsearch.index.numShards索引分片数elasticsearch.index.numReplicas索引副本数elasticsearch.index.numRetries写入重试次数elasticsearch.index.refreshIntervalSeconds索引刷新间隔秒elasticsearch.index.settingsOverrides按索引名的 settings 覆盖JSONelasticsearch.index.entitySettingsOverrides按实体索引名的 settings 覆盖JSONelasticsearch.index.enableSettingsReindex是否允许 settings 变更触发重建elasticsearch.index.enableMappingsReindex是否允许 mappings 变更触发重建elasticsearch.index.maxReindexHours重建索引的最大时长小时此外SearchDocumentTransformerFactory.java 将elasticsearch.index.maxArrayLength、elasticsearch.index.maxObjectKeys、elasticsearch.index.maxValueLength以及structuredProperties.keywordMaxLength组装为searchDocumentTransformerBean。其中keywordMaxLength的兜底默认值在 ESUtils.java 中定义为KEYWORD_MAXLENGTH 32766字节用于限制 keyword 类型字段的长度超长值可按structuredProperties.isDropOversizedKeywordValuesFromIndex配置决定是否丢弃。索引更新的触发链路在整体服务架构中见 metadata-serving.md元数据变更先持久化并产生 MCLMetadata Change Log经 Kafka 发送随后由mae-consumer-job消费并将变更应用到 Graph 与 Search Index。该任务与实体类型无关按实体 URN 分 key 保证同一实体的变更按时间顺序被单线程顺序处理从而确保 Search Document 的更新不会乱序。搜索 API 返回模型文档字段如何驱动结果搜索文档中的属性最终通过搜索 API 暴露给调用方。在 SearchEntity.pdl 中每条搜索结果的模型包括entity: Urn命中的实体标识matchedFields: array[record MatchedField { name, value }]命中的字段名与值——这正是 Snippet 摘要格式化的数据来源features: optional map[string, double]特征打分score: optional double相关性得分extraFields: optional map[string, string]根据搜索请求从 Search Document 中额外返回的字段。也就是说你在搜索 API 里看到的命中摘要、高亮字段本质上都是Search Document 中已索引字段的回显——这再次印证了文档属性既用于过滤、又用于摘要格式化的设计初衷。搜索返回的聚合aggregation、建议suggestion等结果模型同样定义在 metadata-models/src/main/pegasus/com/linkedin/metadata/search/ 目录下如SearchResult.pdl、SearchSuggestion.pdl等。相关概念串联与扩展阅读Search Document 并非孤立概念它与 DataHub 元数据模型的各个基础构件紧密耦合AspectSearch Document 字段值的来源。Aspect 是不可变的结构化记录任何对 Aspect 的修改都会产生新版本RelationshipownedDatasets这类字段往往隐式承载实体间关系关系可通过Relationship注解显式建模并从 Aspect 中提取URN文档主键与实体标识的统一定义方式Search Index文档类型到 Elasticsearch 索引的映射以及部分更新、成员测试、零停机切换等能力说明Metadata Serving从 MCL 到索引更新的完整服务链路。如果你需要为新的实体类型扩展搜索能力核心工作就是两件事定义该实体类型的 Search Document PDL含urn与各类optional字段以及编写对应的 Index Builder 逻辑或声明 Aspect 中的searchableFieldSpecs使文档字段能够从元数据 Aspect 中被正确提取并保持同步更新。【免费下载链接】datahubThe Context Platform for your Data and AI Stack项目地址: https://gitcode.com/GitHub_Trending/da/datahub创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进