十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

NocoBase 数据源管理核心接口 ICollection 详解:从接口定义到模型实现的完整指南

NocoBase 数据源管理核心接口 ICollection 详解:从接口定义到模型实现的完整指南 NocoBase 数据源管理核心接口 ICollection 详解从接口定义到模型实现的完整指南【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobaseICollection是 NocoBase 数据源管理Data Source Manager模块中对数据模型的抽象接口它统一描述了数据集合的名称、字段、关联关系以及数据读写入口repository。无论底层是 Sequelize 数据库还是其他数据源上层代码都通过ICollection与模型打交道。读完本文你将理解ICollection的完整接口契约、每个方法的签名与底层实现并掌握如何通过CollectionManager获取、扩展集合以及操作字段的实战方法。ICollection 在数据源管理架构中的位置NocoBase 支持接入多种数据源主数据库、外部数据库、API 数据源等为此在 packages/core/data-source-manager 中抽象出一套面向数据源的统一接口层。从源码结构看其核心调用链为DataSourceManager管理多个 DataSource └─ DataSource数据源实例持有 CollectionManager └─ CollectionManager实现 ICollectionManager ├─ defineCollection() / getCollection() 返回 ICollection └─ ICollection数据模型抽象 └─ IRepository数据读写入口其中DataSourceManager见>export interface ICollection { repository: IRepository; updateOptions(options: CollectionOptions, mergeOptions?: MergeOptions): void; setField(name: string, options: any): IField; removeField(name: string): void; getFields(): ArrayIField; getField(name: string): IField; getFieldByField(field: string): IField; [key: string]: any; unavailableActions?: () string[]; availableActions?: () string[]; }可以看到接口包含三部分内容数据入口repository属性类型为IRepository负责对该集合数据的增删改查模型元数据操作updateOptions()、setField()、removeField()、getFields()、getField()管理集合的属性与字段扩展点索引签名[key: string]: any允许实现类携带任意扩展属性availableActions/unavailableActions用于声明集合可用的操作。与接口密切相关的还有两个类型同样定义在 types.tsexport interface CollectionOptions { name: string; // 集合唯一名称 schema?: string; // 数据库 schema tableName: string; // 物理表名 title?: string; // 显示标题 template?: string; // 模板名 timestamps?: boolean; // 是否自动维护 createdAt / updatedAt filterTargetKey?: string | Arraystring; // 过滤主键 fields: FieldOptions[]; // 字段定义数组 autoGenId?: boolean; // 是否自动生成主键 view?: boolean; // 是否为视图集合 unsupportedFields?: UnsupportedFieldOptions[]; // 不支持的字段逆向表时出现 [key: string]: any; } export interface FieldOptions { name: string; // 字段名 field: string; // 物理列名 rawType: string; // 原始数据库类型 type: string; // 字段类型如 string、integer description?: string; interface?: string; // 界面接口类型 uiSchema?: any; // UI Schema possibleTypes?: string[]; defaultValue?: any; primaryKey?: boolean; unique?: boolean; allowNull?: boolean; autoIncrement?: boolean; [key: string]: any; }成员详解repository —— 集合的数据读写入口repository是ICollection上唯一以属性形式暴露的核心成员类型为IRepository。IRepository的契约定义于 types.tsexport interface IRepository { find(options?: FindOptions): PromiseIModel[]; findOne(options?: any): PromiseIModel; count(options?: any): PromiseNumber; findAndCount(options?: any): Promise[IModel[], Number]; create(options: any): any; update(options: any): any; destroy(options: any): any; [key: string]: any; }从源码结构看repository的注入由集合实现类完成在 collection.ts 中setRepository()通过CollectionManager.getRegisteredRepository()从注册表中取出 Repository 类并实例化protected setRepository(repository: any) { const RepositoryClass this.collectionManager.getRegisteredRepository(repository || Repository); this.repository new RepositoryClass(this); }也就是说一个ICollection实例被创建时其repository即被绑定为该集合专属的数据操作对象你也可以通过updateOptions({ repository })在运行时替换。默认的 Repository 基类位于 repository.ts实现了IRepository的全部方法而 Sequelize 场景下实际的 Repository 由 nocobase/database 提供getRepository()见 sequelize-collection-manager.ts。API 逐个解析五个方法签名与底层实现updateOptions(options): 更新集合属性签名updateOptions(options: CollectionOptions, mergeOptions?: MergeOptions): void用于更新Collection的属性名称、表名、标题、时间戳等配置。Collection实现类的逻辑见 collection.tsupdateOptions(options: CollectionOptions, mergeOptions?: any) { const newOptions { ...this.options, ...lodash.cloneDeep(options), }; this.options newOptions; this.setFields(newOptions.fields || []); if (options.repository) { this.setRepository(options.repository); } return this; }注意三个关键行为新配置通过浅合并 深拷贝方式覆盖旧配置更新配置时会同步重建全部字段调用setFields因此传入的fields若缺失则清空字段更新时务必带上完整字段列表若传入repository会同时替换数据入口。在数据源管理中extendCollection()正是基于此方法实现集合扩展见 collection-manager.ts。setField(name, options): 设置字段签名setField(name: string, options: any): IField向集合新增或覆盖一个字段并返回字段实例。Collection实现类将其包装为CollectionField后存入fieldsMapcollection.tssetField(name: string, options: any) { const field new CollectionField(options); this.fields.set(name, field); return field; }CollectionField见 collection-field.ts实现了IField接口内部持有options: FieldOptions并对外提供isRelationField()判断是否为关联字段——这是后续判断字段是否触发关联关系belongsTo / hasMany 等的重要依据。在数据库实现中setField还会同步构建 Sequelize 模型属性。removeField(name): 移除字段签名removeField(name: string): void按名称删除字段实现即从fieldsMap 中删除对应键collection.tsremoveField(name: string) { this.fields.delete(name); }getFields(): 获取全部字段签名getFields(): ArrayIField返回该集合全部字段实例的数组getFields() { return [...this.fields.values()]; }返回值可直接用于遍历例如批量读取每个字段的options.name、options.type做校验或生成 UI Schema。getField(name): 按名称获取字段签名getField(name: string): IField按字段名取单个字段不存在时返回undefined。除文档列出的getField外源码中的Collection还额外实现了getFieldByField(field)collection.ts它按物理列名field而非字段名查找在数据库逆向introspection场景中非常实用getFieldByField(field: string): IField { for (const item of this.fields.values()) { if (item.options.field field) { return item; } } return null; }从接口到实现两种 CollectionManager 的差异化落地ICollection是纯接口具体实现取决于CollectionManager的实现类型。在 packages/core/data-source-manager/src 中存在两条实现路径1. 内存版Collection通用/自定义数据源collection.ts 中的Collection类直接实现ICollection以Mapstring, IField在内存中维护字段构造时自动完成setRepository与字段初始化export class Collection implements ICollection { repository: IRepository; fields: Mapstring, IField new Mapstring, IField(); constructor( protected options: CollectionOptions, public collectionManager: ICollectionManager, ) { this.setRepository(options.repository); if (options.fields) { this.setFields(options.fields); } } }它由CollectionManagercollection-manager.ts通过defineCollection()、getCollection()等统一创建与管理。2. Sequelize 版主数据库 / 关系型数据库sequelize-collection-manager.ts 中的SequelizeCollectionManager则将ICollection的实现委托给 nocobase/database 的Collection类见 collection.ts。该实现持有真实的 Sequelizemodel、repository并在构造时完成modelInit()、字段注册与表名映射// packages/core/database/src/collection.ts export class Collection... extends EventEmitter { options: CollectionOptions; fields: Mapstring, any; model: ModelStaticModel; repository: Repository...; constructor(options: CollectionOptions, context: CollectionContext) { super(); this.context context; this.options options; this.checkOptions(options); this.bindFieldEventListener(); this.modelInit(); // ... 表名 / 模型映射注册 this.setFields(options.fields); this.setRepository(options.repository); this.setSortable(options.sortable); } }这也解释了为什么业务代码只依赖ICollection无论底层是内存 Map 还是 Sequelize 模型上层拿到的都是同一套字段管理与数据读写接口。实战如何获取与操作一个 ICollection在实际开发中通常通过CollectionManagerICollectionManager拿到ICollection实例// 1. 定义一个新集合返回 ICollection const collection: ICollection collectionManager.defineCollection({ name: posts, tableName: posts, fields: [ { name: id, type: integer, primaryKey: true, autoIncrement: true }, { name: title, type: string }, ], }); // 2. 查询集合与字段 if (collectionManager.hasCollection(posts)) { const posts collectionManager.getCollection(posts); posts.getFields().forEach((f) console.log(f.options.name, f.options.type)); const titleField posts.getField(title); } // 3. 运行时扩展集合合并字段 collectionManager.extendCollection({ name: posts, fields: [ { name: authorId, type: integer }, ], }); // 4. 通过 repository 读写数据 const rows await collectionManager.getRepository(posts).find({ filter: { title: { $like: %NocoBase% } } }); const one await collectionManager.getRepository(posts).create({ values: { title: Hello } });几点实战注意defineCollection()后集合即注册到管理器extendCollection()本质是getCollection(name).updateOptions(...)collection-manager.ts因此扩展时fields需提供完整字段列表否则会清空原字段字段类型、主键、唯一约束等通过FieldOptions声明具体取值范围与底层数据源类型映射有关Sequelize 场景下可参考 packages/core/database 的字段类型注册在多数据源应用中DataSourceManager会依据请求头x-data-source选择对应数据源data-source-manager.ts默认回落到main数据源因此同一套ICollection抽象可平滑切换不同数据源。小结ICollection是 NocoBase 数据源管理模块中数据模型的统一抽象repository打通数据读写setField/removeField/getFields/getField完成字段的增删查updateOptions支持运行时调整集合配置。理解它是掌握 NocoBase 数据源架构、编写自定义数据源插件或深入CollectionManager二次开发的前提。接口契约见 types.ts默认实现见 collection.tsSequelize 落地路径可继续阅读 sequelize-collection-manager.ts 与 packages/core/database/src/collection.ts。【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表