DataHub OpenAPI 使用指南:REST API 端点、批量读写与通用 Patching 实战

发布时间:2026/9/16 15:32:19
DataHub OpenAPI 使用指南:REST API 端点、批量读写与通用 Patching 实战 DataHub OpenAPI 使用指南REST API 端点、批量读写与通用 Patching 实战【免费下载链接】datahubThe Context Platform for your Data and AI Stack项目地址: https://gitcode.com/GitHub_Trending/da/datahub本篇技术指南围绕 DataHubThe Context Platform for your Data and AI Stack的 OpenAPI v3 REST 端点展开讲解如何在 GMS 上定位 Swagger UI 与原始 OpenAPI 规范、通过/entities、/relationships、/timeline、/platform四组端点完成元数据的增删改查并深入介绍 OpenAPI v3 的批量读取Batch Get、条件写入与基于arrayPrimaryKeys的通用 JSON Patch。读完本文你将掌握使用curl、Postman 和 Java Rest Emitter 三种方式与 DataHub OpenAPI 交互的完整技能并理解这些端点背后的源码实现。为什么选择 OpenAPIOpenAPI 标准是 RESTful API 广泛采用的文档与设计规范。为了让外部系统更容易与 DataHub 集成DataHub 发布了一组基于 OpenAPI 的端点。它与 DataHub 已有的 GraphQL API、Rest.li API 各自承担不同的职责具体选用哪种 API 取决于你的使用场景可先阅读 DataHub API 总览 了解各 API 的设计动机与适用边界。从源码结构看OpenAPI 端点由独立的 servlet 模块承载位于 metadata-service/openapi-servlet其中 v1 的控制器/openapi/entities/v1、/openapi/relationships/v1、/openapi/timeline/v1和 v3 的控制器/openapi/v3/entity均基于 Spring MVC 与 SpringDoc 自动生成规范文档。定位 OpenAPI 端点目前OpenAPI 端点被隔离在 GMS 上的一个 servlet 中随 GMS 服务器自动部署。该 servlet 自带 OpenAPI UI即 Swagger UI访问地址为GMS_SERVER_HOST:GMS_PORT/openapi/swagger-ui/index.html例如本地 Quickstart 环境即为http://localhost:8080/openapi/swagger-ui/index.html。DataHub 前端frontend同样以代理方式暴露这一端点只需把 GMS 的主机与端口替换为 DataHub 前端的地址即可本地 Quickstart 链接为http://localhost:9002/openapi/swagger-ui/index.html同时它也以链接形式出现在前端右上角用户头像下的下拉菜单中方便在 UI 中直接打开。此外可以直接获取 OpenAPI 规范的原始 JSON 或 YAML 格式BASE_URL/openapi/v3/api-docsBASE_URL/openapi/v3/api-docs.yaml原始规范文件可以输入到 codegen 系统生成你偏好的编程语言的客户端代码。不同语言在 codegen 体系中的成熟度不一部分语言可能需要一定定制才能完全兼容。OpenAPI UI 中还包含完整的、可浏览的请求与响应对象 Schema——这些模型全部在构建期由 PDL 模型自动生成转换为 JSON Schema 兼容的 Java 模型因此 UI 上展示的结构与后端实际接收/返回的结构严格一致。理解 OpenAPI 端点完整的 OpenAPI 规范始终可以在GMS_SERVER_HOST:GMS_PORT/openapi/swagger-ui/index.html查看这里先给出主要端点及其用途的快速总览。实体/entities实体端点用于对元数据图进行读写。DataHub 的整个元数据模型都可以写入以 entity 与 aspect 成对的形式也可以读取单个实体的元数据。对应实现见 EntitiesController.java其RequestMapping(/openapi/entities/v1)声明了GET /latest、POST /、DELETE /等操作。关系/relationships关系端点用于查询图从一个实体出发导航到其他实体。对应实现见 RelationshipsController.java它内部委托给GraphService.findRelatedEntities(...)完成图查询。时间线/timeline时间线端点用于查询指定实体在一段时间内的版本化历史。例如你可以查询一个 dataset 历史上发生过的所有 Schema 变更或所有文档描述变更。详细用法参见 时间线开发指南。平台/platform平台端点属于更底层的 API允许以标准格式把元数据事件写入 DataHub 平台Java Rest Emitter 的 OpenAPI 模式正是经由/platform/entities/v1把元数据发送给 GMS。示例请求/entities 端点POSTUPSERT不带任何额外 URL 参数的 POST 会执行实体 aspect 的 UPSERT实体不存在则创建存在则更新。curl --location --request POST localhost:8080/openapi/entities/v1/ \ --header Content-Type: application/json \ --header Accept: application/json \ --header Authorization: Bearer token \ --data-raw [ { aspect: { __type: SchemaMetadata, schemaName: SampleHdfsSchema, platform: urn:li:dataPlatform:platform, platformSchema: { __type: MySqlDDL, tableSchema: schema }, version: 0, created: { time: 1621882982738, actor: urn:li:corpuser:etl, impersonator: urn:li:corpuser:jdoe }, lastModified: { time: 1621882982738, actor: urn:li:corpuser:etl, impersonator: urn:li:corpuser:jdoe }, hash: , fields: [ { fieldPath: county_fips_codefg, jsonPath: null, nullable: true, description: null, type: { type: { __type: StringType } }, nativeDataType: String(), recursive: false }, { fieldPath: county_name, jsonPath: null, nullable: true, description: null, type: { type: { __type: StringType } }, nativeDataType: String(), recursive: false } ] }, entityType: dataset, entityUrn: urn:li:dataset:(urn:li:dataPlatform:platform,testSchemaIngest,PROD) } ]关于请求体各字段的说明aspect要写入的 aspect 内容__type指明 aspect 的具体类型如SchemaMetadata其余字段遵循该类型在 PDL 模型中的定义aspectName可选Postman 示例中显式给出了aspectName: schemaMetadata与aspect.__type对应entityType实体类型如datasetentityUrn目标实体的 URN格式为urn:li:entityType:(...)。POSTCREATE第二个 POST 示例仅当实体不存在时才写入如果实体已存在命令会返回错误而不是覆盖。这里增加了 URL 参数createEntityIfNotExiststruecurl --location --request POST localhost:8080/openapi/entities/v1/?createEntityIfNotExiststrue \ --header Content-Type: application/json \ --header Accept: application/json \ --header Authorization: Bearer token \ --data-raw see previous example如果实体不存在响应与上一个示例完全一致如果实体已存在则会出现如下错误422 ValidationExceptionCollection{EntityAspect:(urn:li:dataset:(urn:li:dataPlatform:platform,testSchemaIngest,PROD),schemaMetadata) Exceptions: [com.linkedin.metadata.aspect.plugins.validation.AspectValidationException: Cannot perform CREATE if not exists since the entity key already exists.]}从源码看该参数在 EntitiesController.java 中以RequestParam(required false, name createEntityIfNotExists) Boolean createEntityIfNotExists接收并随后通过MappingUtil.mapToProposal(req, createIfNotExists, createEntityIfNotExists)映射为对应的 MetadataChangeProposal——也就是说create-if-not-exists 的语义在写入前由映射层转换最终由 aspect 校验插件在实体 key 已存在时抛出AspectValidationException。GETcurl --location --request GET localhost:8080/openapi/entities/v1/latest?urnsurn:li:dataset:(urn:li:dataPlatform:platform,testSchemaIngest,PROD)aspectNamesschemaMetadata \ --header Accept: application/json \ --header Authorization: Bearer token参数说明urns必填原始 URN 字符串列表一次请求只支持单一实体类型aspectNames要检索的 aspect 名称列表不传则返回该实体的全部 aspect。DELETEcurl --location --request DELETE localhost:8080/openapi/entities/v1/?urnsurn:li:dataset:(urn:li:dataPlatform:platform,testSchemaIngest,PROD)softtrue \ --header Accept: application/json \ --header Authorization: Bearer token参数说明urns必填同上soft决定删除是软删除还是硬删除默认true软删除。Postman Collection官方提供了包含单个实体带SchemaMetadataaspect的 POST、GET、DELETE 三个请求的 Postman Collection。它定义了{{baseUrl}}默认localhost:8080与{{token}}两个变量整个 collection 使用 Bearer Token 认证。下面是保留了全部三个请求与查询参数语义的精简可导入版本{ info: { name: DataHub OpenAPI, description: DataHub OpenAPI entities/v1 collection: POST (UPSERT/CREATE), GET latest, DELETE, schema: https://schema.getpostman.com/json/collection/v2.1.0/collection.json }, item: [ { name: entities/v1, item: [ { name: post Entities 1, request: { method: POST, header: [ { key: Content-Type, value: application/json }, { key: Accept, value: application/json } ], body: { mode: raw, raw: [\n {\n \aspect\: {\n \__type\: \SchemaMetadata\,\n \schemaName\: \SampleHdfsSchema\,\n \platform\: \urn:li:dataPlatform:platform\,\n \platformSchema\: {\n \__type\: \MySqlDDL\,\n \tableSchema\: \schema\\n },\n \version\: 0,\n \created\: {\n \time\: 1621882982738,\n \actor\: \urn:li:corpuser:etl\,\n \impersonator\: \urn:li:corpuser:jdoe\\n },\n \lastModified\: {\n \time\: 1621882982738,\n \actor\: \urn:li:corpuser:etl\,\n \impersonator\: \urn:li:corpuser:jdoe\\n },\n \hash\: \\,\n \fields\: [\n {\n \fieldPath\: \county_fips_codefg\,\n \jsonPath\: \null\,\n \nullable\: true,\n \description\: \null\,\n \type\: { \type\: { \__type\: \StringType\ } },\n \nativeDataType\: \String()\,\n \recursive\: false\n },\n {\n \fieldPath\: \county_name\,\n \jsonPath\: \null\,\n \nullable\: true,\n \description\: \null\,\n \type\: { \type\: { \__type\: \StringType\ } },\n \nativeDataType\: \String()\,\n \recursive\: false\n }\n ]\n },\n \aspectName\: \schemaMetadata\,\n \entityType\: \dataset\,\n \entityUrn\: \urn:li:dataset:(urn:li:dataPlatform:platform,testSchemaIngest,PROD)\\n }\n] }, url: { raw: {{baseUrl}}/openapi/entities/v1/, host: [{{baseUrl}}], path: [openapi, entities, v1, ] } }, { name: delete Entities, request: { method: DELETE, header: [{ key: Accept, value: application/json }], url: { raw: {{baseUrl}}/openapi/entities/v1/?urnsurn:li:dataset:(urn:li:dataPlatform:platform,testSchemaIngest,PROD)softtrue, host: [{{baseUrl}}], path: [openapi, entities, v1, ], query: [ { key: urns, value: urn:li:dataset:(urn:li:dataPlatform:platform,testSchemaIngest,PROD), description: (Required) A list of raw urn strings, only supports a single entity type per request. }, { key: soft, value: true, description: Determines whether the delete will be soft or hard, defaults to true for soft delete } ] } } }, { name: get Entities, request: { method: GET, header: [{ key: Accept, value: application/json }], url: { raw: {{baseUrl}}/openapi/entities/v1/latest?urnsurn:li:dataset:(urn:li:dataPlatform:platform,testSchemaIngest,PROD)aspectNamesschemaMetadata, host: [{{baseUrl}}], path: [openapi, entities, v1, latest], query: [ { key: urns, value: urn:li:dataset:(urn:li:dataPlatform:platform,testSchemaIngest,PROD), description: (Required) A list of raw urn strings, only supports a single entity type per request. }, { key: aspectNames, value: schemaMetadata, description: The list of aspect names to retrieve } ] } } } ], auth: { type: bearer, bearer: [{ key: token, value: {{token}}, type: string }] } } ], variable: [ { key: baseUrl, value: localhost:8080, type: string }, { key: token, value: your-access-token, type: default } ] }导入后设置{{baseUrl}}GMS 地址与{{token}}访问令牌参见 Personal Access Tokens 文档即可直接发送请求。/relationships 端点GET示例请求curl -X GET \ http://localhost:8080/openapi/relationships/v1/?urnurn%3Ali%3Acorpuser%3AdatahubrelationshipTypesIsPartOfdirectionINCOMINGstart0count200 \ -H accept: application/json示例响应{ start: 0, count: 2, total: 2, entities: [ { relationshipType: IsPartOf, urn: urn:li:corpGroup:bfoo }, { relationshipType: IsPartOf, urn: urn:li:corpGroup:jdoe } ] }参数与源码对照RelationshipsController.javaurn必填要查询关系的实体 URN源码中会先做一次 URL 解码URLDecoder.decode(urn, UTF-8)因此已编码与未编码的 URN 均可使用relationshipTypes必填要遍历的关系类型列表direction必填关系的方向取值为INCOMING或OUTGOINGstart分页偏移量默认0count从偏移量开始返回的关系数量默认200同时源码中MAX_DOWNSTREAM_CNT 200也作为默认上限。在权限方面该控制器使用AuthUtil.isAPIAuthorizedUrns(opContext, RELATIONSHIP, READ, ...)对目标 URN 做细粒度鉴权未授权会抛出UnauthorizedException成功与失败分别通过 MetricRegistry 记录getRelationships/success与getRelationships/failed指标便于监控调用情况。编程式使用Java Rest Emitter对模型的编程式使用可以通过包含生成模型的 Java Rest Emitter 完成。一个最小的、用于向 OpenAPI 端点发射元数据的 Java 项目需要如下依赖Gradle 格式dependencies { implementation io.acryl:datahub-client:DATAHUB_CLIENT_VERSION implementation org.apache.httpcomponents:httpclient:APACHE_HTTP_CLIENT_VERSION implementation org.apache.httpcomponents:httpasyncclient:APACHE_ASYNC_CLIENT_VERSION }向 /platform 端点写入元数据事件下面的代码通过构造一组UpsertAspectRequest来发射元数据事件。在底层它使用的是/platform/entities/v1端点把元数据发送到 GMSimport io.datahubproject.openapi.generated.DatasetProperties; import datahub.client.rest.RestEmitter; import datahub.event.UpsertAspectRequest; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; public class Main { public static void main(String[] args) throws IOException, ExecutionException, InterruptedException { RestEmitter emitter RestEmitter.createWithDefaults(); ListUpsertAspectRequest requests new ArrayList(); UpsertAspectRequest upsertAspectRequest UpsertAspectRequest.builder() .entityType(dataset) .entityUrn(urn:li:dataset:(urn:li:dataPlatform:bigquery,my-project.my-other-dataset.user-table,PROD)) .aspect(new DatasetProperties().description(This is the canonical User profile dataset)) .build(); UpsertAspectRequest upsertAspectRequest2 UpsertAspectRequest.builder() .entityType(dataset) .entityUrn(urn:li:dataset:(urn:li:dataPlatform:bigquery,my-project.another-dataset.user-table,PROD)) .aspect(new DatasetProperties().description(This is the canonical User profile dataset 2)) .build(); requests.add(upsertAspectRequest); requests.add(upsertAspectRequest2); System.out.println(emitter.emit(requests, null).get()); System.exit(0); } }要点说明RestEmitter.createWithDefaults()会读取环境变量/配置中的 GMS 地址默认localhost:8080并创建发射器emit(requests, null)返回Future.get()阻塞等待 GMS 处理结果每个UpsertAspectRequest由entityType、entityUrn与一个 aspect 对象此处为DatasetProperties构成与 HTTP POST 的请求体结构一一对应生成的模型位于io.datahubproject.openapi.generated包由 PDL 模型自动生成Java client 的生成产物可参考 metadata-integration/java。OpenAPI v3 高级特性条件写入Conditional Writes所有 aspect 的 create/POST 端点都支持在 POST body 中携带headers以支持批量 API。这些 header 的语义如基于版本号的条件写入实现乐观锁式更新详见 MetadataChangeProposal 文档。结合If-Match等条件头可以保证仅在版本未被他人修改时才写入避免并发场景下的覆盖丢失。批量读取Batch Get所有实体都提供形如/v3/entity/{entityName}/batchGet的批量读取端点实现见 EntityController.javaPostMapping(value /{entityName}/batchGet)。该端点允许批量获取实体及其 aspect并且结合If-Version-Matchheader 可以检索指定版本的 aspect默认返回最新版本目前该接口对每个实体/aspect 只返回单一版本但不同实体之间可以指定不同的版本通过 URL 参数systemMetadatatrue可以查看 aspect 的当前版本号。示例请求获取给定 URN 的最新 aspect并打开systemMetadata以查看当前版本[ { urn: urn:li:dataset:(urn:li:dataPlatform:hive,fct_users_deleted,PROD), globalTags: {}, datasetProperties: {} }, { urn: urn:li:dataset:(urn:li:dataPlatform:hive,fct_users_created,PROD), globalTags: {}, datasetProperties: {} } ]示例响应注意systemMetadata中每个已存在的 aspect 都带有version: 1[ { urn: urn:li:dataset:(urn:li:dataPlatform:hive,fct_users_deleted,PROD), datasetProperties: { value: { description: table containing all the users deleted on a single day, customProperties: { encoding: utf-8 }, tags: [] }, systemMetadata: { properties: { clientVersion: 1!0.0.0.dev0, clientId: acryl-datahub }, version: 1, lastObserved: 1720781548776, lastRunId: file-2024_07_12-05_52_28, runId: file-2024_07_12-05_52_28 } } }, { urn: urn:li:dataset:(urn:li:dataPlatform:hive,fct_users_created,PROD), datasetProperties: { value: { description: table containing all the users created on a single day, customProperties: { encoding: utf-8 }, tags: [] }, systemMetadata: { properties: { clientVersion: 1!0.0.0.dev0, clientId: acryl-datahub }, version: 1, lastObserved: 1720781548773, lastRunId: file-2024_07_12-05_52_28, runId: file-2024_07_12-05_52_28 } } }, { urn: urn:li:dataset:(urn:li:dataPlatform:hive,fct_users_created,PROD), globalTags: { value: { tags: [ { tag: urn:li:tag:NeedsDocumentation } ] }, systemMetadata: { properties: { appSource: ui }, version: 1, lastObserved: 0, lastRunId: no-run-id-provided, runId: no-run-id-provided } } } ]接下来我们为第二个 URN 的globalTags增加一个新 tag这会将该 aspect 的版本递增。修改后再次批量读取注意globalTags的systemMetadata中version: 2并且 tags 中出现了两个 tag新增了urn:li:tag:Legacy[ { urn: urn:li:dataset:(urn:li:dataPlatform:hive,fct_users_deleted,PROD), datasetProperties: { value: { description: table containing all the users deleted on a single day, customProperties: { encoding: utf-8 }, tags: [] }, systemMetadata: { properties: { clientVersion: 1!0.0.0.dev0, clientId: acryl-datahub }, version: 1, lastObserved: 1720781548776, lastRunId: file-2024_07_12-05_52_28, runId: file-2024_07_12-05_52_28 } } }, { urn: urn:li:dataset:(urn:li:dataPlatform:hive,fct_users_created,PROD), datasetProperties: { value: { description: table containing all the users created on a single day, customProperties: { encoding: utf-8 }, tags: [] }, systemMetadata: { properties: { clientVersion: 1!0.0.0.dev0, clientId: acryl-datahub }, version: 1, lastObserved: 1720781548773, lastRunId: file-2024_07_12-05_52_28, runId: file-2024_07_12-05_52_28 } } }, { urn: urn:li:dataset:(urn:li:dataPlatform:hive,fct_users_created,PROD), globalTags: { value: { tags: [ { tag: urn:li:tag:NeedsDocumentation }, { tag: urn:li:tag:Legacy } ] }, systemMetadata: { properties: { appSource: ui }, version: 2, lastObserved: 0, lastRunId: no-run-id-provided, runId: no-run-id-provided } } } ]最后我们通过If-Version-Match头取回已升级到版本 2 的那个globalTagsaspect 的上一版本版本 1。只需在请求体对应 aspect 的headers中填充If-Version-Match示例请求[ { urn: urn:li:dataset:(urn:li:dataPlatform:hive,fct_users_created,PROD), globalTags: { headers: { If-Version-Match: 1 } } } ]示例响应如预期返回了globalTags的版本1仅包含单个 tag[ { urn: urn:li:dataset:(urn:li:dataPlatform:hive,fct_users_created,PROD), globalTags: { value: { tags: [ { tag: urn:li:tag:NeedsDocumentation } ] }, systemMetadata: { properties: { appSource: ui }, version: 1, lastObserved: 0, lastRunId: no-run-id-provided, runId: no-run-id-provided } } } ]版本匹配相关的异常处理可在 GlobalControllerExceptionHandler.java 中查看它统一把条件版本不匹配等错误转换为标准的 HTTP 错误响应。通用 PatchingGeneric PatchingOpenAPI v3 的 PATCH 端点相比此前的 patch 支持有一个关键优势去除了后端为每种 aspect 单独编写 patch 处理代码的需要参见 Template Classes 实现细节。该技术利用 aspect 天然的 JSON 结构在 JSON Patch 标准RFC 6902之上扩展出一套通用 patching 机制并为数组操作做了显著增强。注意为了保持向后兼容默认仍使用传统的 patch 模板只有当arrayPrimaryKeys非空或forceGenericPatch设置为true时才会激活通用 patching。从源码看PATCH 端点定义在 EntityController.javaPatchMapping(value /{entityName})同时接受application/json-patchjson与application/json两种 Content-Type请求体被转换为ChangeType.PATCH的 MetadataChangeProposal 批处理再交由entityService.ingestProposal(...)执行并支持async参数默认true异步时返回 202 Accepted。针对数组的高级 JSON Patch标准 JSON Patch 的局限JSON Patch 标准对数组的修改主要依赖基于索引的操作add/[index]在指定位置插入remove/[index]移除指定位置的元素replace/[index]替换指定位置的元素在以下场景中这种基于索引的方式会带来问题数组顺序不可预测或可能变化多个客户端并发修改同一资源客户端并不掌握数组当前的索引。核心概念数组主键Array Primary KeysDataHub 通过arrayPrimaryKeys字段把数组操作转换为类 map 操作从而扩展 JSON Patch 标准数组在概念上被当作 map其中每个元素都可以通过其主键寻址主键可以是复合的由多个字段组合而成路径表达式使用这些主键而不是数字索引后端负责在 map 式操作与实际数组修改之间进行转换。这种方式带来的好处无论数组顺序如何操作都是幂等的可以在不了解当前数组状态的情况下进行精准修改并发更新互不冲突只要修改的是不同的数组元素API 使用更直观、更易维护。主键定义与路径构造下面以最常见的 patch 场景为例在考虑 tag 归属来源attribution source的前提下添加/移除全局 tags。以下示例专门修改globalTagsaspect。定义主键arrayPrimaryKeys属性指定了哪些字段可以唯一标识每个数组元素{ arrayPrimaryKeys: { tags: [attribution␟source, tag] }, patch: [ { op: add, path: /tags/urn:li:platformResource:source1/urn:li:tag:tag1, value: { tag: urn:li:tag:tag1, attribution: { source: urn:li:platformResource:source1, actor: urn:li:corpuser:user, time: 0 } } } ] }在这个例子中tags是被 patch 的数组字段主键是attribution.source与tag的复合␟Unit SeparatorU241F分隔符表示第一个键分量中的嵌套路径即attribution␟source表示attribution对象下的source字段。路径构造后端处理 patch 操作时会依次使用指定的主键字段把数组转换为 map针对这个 map 表示执行操作把 map 再转换回数组进行存储。例如对于路径/tags/urn:li:platformResource:source1/urn:li:tag:tag1系统会识别出tags是目标数组用urn:li:platformResource:source1作为attribution.source的值用urn:li:tag:tag1作为 tag 的值找到具有这些键值的匹配数组元素。支持的操作实现支持标准的 JSON Patch 操作OperationDescriptionadd添加新元素若已存在则替换remove移除匹配键的元素Patch 操作示例添加带 Attribution 的 Tag 元素{ op: add, path: /tags/urn:li:platformResource:source1/urn:li:tag:tag1, value: { tag: urn:li:tag:tag1, attribution: { source: urn:li:platformResource:source1, actor: urn:li:corpuser:user, time: 0 } } }该操作的行为检查数组中是否存在主键匹配的元素如果不存在添加新元素如果已存在替换现有元素。选择性移除{ op: remove, path: /tags/urn:li:platformResource:source1/urn:li:tag:tag1 }该操作的行为找到匹配复合键的元素只移除这些元素保留其他元素即使其键部分匹配。在测试侧EntityControllerTest.java 的 PATCH 用例请求体中就包含arrayPrimaryKeys可以对照测试来验证add/remove在globalTags等数组 aspect 上的实际行为与响应结构。小结DataHub 的 OpenAPI 端点提供了一条与 Rest.li 并行的、基于标准 REST 风格与 OpenAPI 规范的集成路径通过GET GMS:8080/openapi/swagger-ui/index.html即可浏览全部端点与 Schema原始规范可从/openapi/v3/api-docs与/openapi/v3/api-docs.yaml获取并用于 codegen/entities负责实体 aspect 的 UPSERT / CREATE / GET / DELETE/relationships负责图关系导航/timeline负责版本历史/platform负责底层元数据事件写入v3 接口进一步提供了batchGet批量读取、基于If-Version-Match的版本化读取以及基于arrayPrimaryKeys的通用 PATCH 能力让数组类 aspect如globalTags的并发修改变得幂等与可控。无论是通过curl快速验证、Postman 进行接口调试还是用 Java Rest Emitter 编写集成代码OpenAPI 端点都能满足从简单读写到复杂条件更新的各类元数据操作需求。【免费下载链接】datahubThe Context Platform for your Data and AI Stack项目地址: https://gitcode.com/GitHub_Trending/da/datahub创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询