后端【免费下载链接】mikro-ormTypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, MariaDB, MS SQL Server, PostgreSQL and SQLite/libSQL databases.项目地址https://gitcode.com/gh_mirrors/mi/mikro-orm点击查看免费下载物化视图Materialized View将查询结果物理存储下来以数据新鲜度为代价换取更快的读取性能与普通视图不同物化视图必须显式刷新才能反映底层数据的变化。本文基于 MikroORM 当前仓库v7.0 文档线讲解如何通过实体定义、refreshMaterializedView()调用与 Schema Generator 全流程管理 PostgreSQL 物化视图读者读完可以掌握四种实体定义方式、WITH DATA/WITH NO DATA的创建控制、并发刷新、只读语义以及物化视图索引的 diff 与生成细节。物化视图与普通视图的本质区别在 MikroORM 中视图View是一种特殊的实体形态它不对应真实数据表而是对应一段SELECT查询表达式。普通视图view: true只是查询的别名每次查询都会实时执行底层 SQL物化视图view: { materialized: true }则把查询结果物理落盘后续读取直接扫描存储的数据因此读取更快但数据是快照需要手动刷新。这一区分在仓库元数据层有明确体现。在 packages/core/src/metadata/types.ts 中view选项的类型定义为view?: boolean | { materialized?: boolean; withData?: boolean };view: true表示普通视图view: { materialized: true }表示物化视图仅 PostgreSQLview: { materialized: true, withData: false }表示创建时不填充数据的物化视图。平台支持度由 packages/core/src/platforms/Platform.ts 的supportsMaterializedViews()控制基类默认返回false而 PostgreSQL 平台在 packages/sql/src/dialects/postgresql/BasePostgreSqlPlatform.ts 中将其重写为true——这正是物化视图仅限 PostgreSQL限制的底层来源。定义物化视图实体创建物化视图实体只需在实体选项中配置view: { materialized: true }并通过expression提供视图的查询定义。MikroORM 支持四种定义风格下面以一个统计每位作者书籍数量的AuthorStats实体为例逐一说明。defineEntity class推荐import { defineEntity, p } from mikro-orm/postgresql; const AuthorStatsSchema defineEntity({ name: AuthorStats, tableName: author_stats_matview, view: { materialized: true }, expression: select a.id, a.name, count(b.id)::int as book_count from author a left join book b on b.author_id a.id group by a.id , properties: { id: p.integer().primary(), name: p.string(), bookCount: p.integer(), }, }); export class AuthorStats extends AuthorStatsSchema.class {} AuthorStatsSchema.setClass(AuthorStats);defineEntity仅 Schema 常量如果不希望定义实体类只导出 Schema 常量即可import { defineEntity, p } from mikro-orm/postgresql; export const AuthorStats defineEntity({ name: AuthorStats, tableName: author_stats_matview, view: { materialized: true }, expression: select a.id, a.name, count(b.id)::int as book_count from author a left join book b on b.author_id a.id group by a.id , properties: { id: p.integer().primary(), name: p.string(), bookCount: p.integer(), }, });reflect-metadata装饰器 元数据反射使用Entity装饰器并在类属性上使用PrimaryKey/Propertyimport { Entity, Property, PrimaryKey } from mikro-orm/postgresql; Entity({ tableName: author_stats_matview, view: { materialized: true }, expression: select a.id, a.name, count(b.id)::int as book_count from author a left join book b on b.author_id a.id group by a.id , }) export class AuthorStats { PrimaryKey() id!: number; Property() name!: string; Property() bookCount!: number; }ts-morph静态代码分析使用 ts-morph 提供元数据时实体定义与 reflect-metadata 风格完全一致只是元数据发现机制不同import { Entity, Property, PrimaryKey } from mikro-orm/postgresql; Entity({ tableName: author_stats_matview, view: { materialized: true }, expression: select a.id, a.name, count(b.id)::int as book_count from author a left join book b on b.author_id a.id group by a.id , }) export class AuthorStats { PrimaryKey() id!: number; Property() name!: string; Property() bookCount!: number; }无论哪种方式实体属性都必须与expression中SELECT返回的列一一对应属性名遵循 MikroORM 的列名到属性名的映射规则如book_count映射为bookCount。从测试看元数据形态仓库测试 tests/features/view-entities/view-entities.postgres.test.ts 同样用defineEntity定义了AuthorStatsMaterializedview: { materialized: true }与AuthorStatsNoDataview: { materialized: true, withData: false }并在 第 976-981 行 断言其元数据expect(meta.view).toBe(true); expect(meta.materialized).toBe(true); expect(meta.readonly).toBe(true);即物化视图实体在元数据层面会自动带有view: true、materialized: true、readonly: true三个标记。创建无数据的物化视图WITH NO DATA默认情况下物化视图创建时会立即填充数据对应 PostgreSQL 的WITH DATA。如果希望在创建时生成一个空视图、稍后再填充数据可以设置withData: falseconst AuthorStats defineEntity({ name: AuthorStats, tableName: author_stats_matview, view: { materialized: true, withData: false }, // Creates with WITH NO DATA expression: select ..., properties: { ... }, });这一选项在以下场景特别有用创建 Schema 时底层表还是空的立即执行SELECT没有意义希望完全掌控初始数据填充的时机先建库建视图再由应用或定时任务触发首次REFRESH。在底层 SQL 生成层面该开关由 packages/sql/src/dialects/postgresql/PostgreSqlSchemaHelper.ts 的createMaterializedView方法处理override createMaterializedView( name: string, schema: string | undefined, definition: string, withData true, ): string { const viewName this.quote(this.getTableName(name, schema)); const dataClause withData ? with data : with no data; return create materialized view ${viewName} as ${definition}${dataClause}; }withData参数默认值为true只有显式传false时才会追加with no data子句。刷新物化视图物化视图缓存了查询结果数据变更后必须刷新才能看到最新数据。MikroORM 在PostgreSqlEntityManager上提供了refreshMaterializedView方法import { MikroORM, EntityManager } from mikro-orm/postgresql; const orm await MikroORM.init({ ... }); const em orm.em; // Refresh the materialized view await em.refreshMaterializedView(AuthorStats); // Now queries will return the updated data const stats await em.find(AuthorStats, {});底层实现解析该方法定义在 packages/sql/src/dialects/postgresql/BasePostgreSqlEntityManager.tspg与pglite的 EntityManager 共同基类。其核心逻辑为通过this.getMetadata(entityName)获取实体元数据校验meta.view meta.materialized若目标实体不是物化视图则抛出Entity ${meta.className} is not a materialized view错误——测试 第 1036-1038 行 专门验证了这一行为从驱动平台取得 SchemaHelper拼接 SQLrefresh materialized view table通过this.execute(sql)执行。对应的 SQL 生成在 PostgreSqlSchemaHelper.ts 第 218-221 行override refreshMaterializedView(name: string, schema?: string, concurrently false): string { const concurrent concurrently ? concurrently : ; return refresh materialized view${concurrent} ${this.quote(this.getTableName(name, schema))}; }并发刷新Concurrent RefreshPostgreSQL 支持并发刷新物化视图——刷新过程中读操作不会被阻塞。并发刷新要求物化视图上至少存在一个唯一索引否则 PostgreSQL 会直接报错// Refresh concurrently (requires unique index on the view) await em.refreshMaterializedView(AuthorStats, { concurrently: true });注意并发刷新要求物化视图上至少有一个唯一索引。缺少唯一索引时 PostgreSQL 会抛出错误。对应生成的 SQL 为refresh materialized view concurrently author_stats_matview。刷新是重量级操作生产环境中应结合唯一索引与低峰期窗口使用详见下文最佳实践。刷新后的数据可见性注意 MikroORM 的 Identity Map 机制同一 EntityManager 中刷新视图后已加载的实体快照不会自动失效建议在刷新后em.clear()或使用 fork 出来的新 EntityManager 查询。测试 第 1014-1034 行 展示了完整链路插入新作者数据 → 刷新前查询仍只有旧数据 →refreshMaterializedView()→em.clear()→ 再次查询即能看到新数据。查询物化视图物化视图实体与普通实体一样可以使用em.find/em.findOne配合条件进行查询// Find all const allStats await em.find(AuthorStats, {}); // Find with conditions const prolificAuthors await em.find(AuthorStats, { bookCount: { $gte: 5 }, }); // Find one const authorStats await em.findOne(AuthorStats, { name: Jon Snow });查询操作直接命中物理存储的数据因此性能稳定。测试 第 994-1012 行 验证了插入数据 → 刷新视图 → 查询得到聚合结果的完整流程。只读行为物化视图实体会被自动标记为只读readonly: true尝试对其持久化修改会失败const stats await em.findOne(AuthorStats, { id: 1 }); stats.bookCount 100; // This change wont be persisted await em.flush(); // No UPDATE will be generated for this entity这一行为由元数据层的readonly标记驱动见前文测试断言Unit of Work 在flush时不会为只读实体生成任何UPDATE语句。物化视图数据的唯一合法更新途径是执行REFRESH MATERIALIZED VIEW。Schema 生成Schema Generator 对物化视图提供全自动支持// Create schema (includes CREATE MATERIALIZED VIEW statements) await orm.schema.create(); // Drop schema (includes DROP MATERIALIZED VIEW statements) await orm.schema.drop(); // Update schema (detects changes to materialized views) await orm.schema.update();生成的 SQL创建物化视图默认WITH DATA会生成create materialized view author_stats_matview as select a.id, a.name, count(b.id)::int as book_count from author a left join book b on b.author_id a.id group by a.id with data;设置withData: false时create materialized view author_stats_matview as select ... with no data;源码层面的生成与 diff 逻辑视图的创建、删除、更新逻辑集中在 packages/sql/src/schema/SqlSchemaGenerator.ts创建appendViewCreation第 795-812 行根据view.materialized分发到createMaterializedView并追加WITH NO DATA视图的索引创建——但跳过withData false的视图的索引此时视图还没有数据可索引索引会在数据填充后的下一次schema:update中创建删除drop与update流程第 248-253 行、第 400-423 行按依赖顺序先删视图再删表物化视图走dropMaterializedViewIfExists生成drop materialized view if exists xxx cascade变更检测packages/sql/src/schema/SchemaComparator.ts 对物化视图的索引使用现有的表 diff 基础设施进行增删改检测通过构造临时DatabaseTable复用diffTable逻辑从而让schema:update能自动发现物化视图上索引的变化。测试 tests/features/schema-generator/materialized-view-diffing.postgres.test.ts 覆盖了新增/删除/修改物化视图、withData切换、schema:create与schema:update生成索引GH #7417等场景可当作行为规范参考。其中 第 236-268 行 验证了关键细节withData: false期间不生成索引 diff切换为withData: true后schema:update才会补建唯一索引且不会自动刷新视图——索引建立在空数据上是合法的PostgreSQL 允许对未刷新视图建索引索引保持空直到下次REFRESH。另外要注意物化视图只支持索引不支持其他表级结构其DatabaseView模型packages/sql/src/typings.ts仅包含materialized、withData与indexes三个物化视图专属字段。限制仅限 PostgreSQL物化视图只在 PostgreSQL 平台受支持。其他数据库平台一旦使用view: { materialized: true }就会报错。这一限制的根因在 packages/sql/src/schema/SchemaHelper.ts基类的createMaterializedView、dropMaterializedViewIfExists、refreshMaterializedView、getListMaterializedViewsSQL、loadMaterializedViews全部直接throw new Error(Not supported by given driver)仅 PostgreSQL 的 SchemaHelper 进行了 override。无自动刷新MikroORM 不会自动刷新物化视图。必须手动调用refreshMaterializedView()或在数据库层面建立刷新机制触发器、pg_cron 定时任务等。最佳实践选择合适的刷新策略对于频繁变化的数据优先考虑普通视图view: true物化视图适合变化不频繁、或可以接受一定时间延迟的数据聚合报表、统计看板、跨表 JOIN 的昂贵查询。为物化视图加索引物化视图支持索引。为高频查询的列建立索引尤其要满足并发刷新的前提CREATE UNIQUE INDEX author_stats_id_idx ON author_stats_matview (id); CREATE INDEX author_stats_book_count_idx ON author_stats_matview (book_count);索引可以在实体元数据中声明由schema:create/schema:update自动生成也可以直接用 SQL 手工创建。调度刷新使用数据库调度器pg_cron或应用层调度在低流量时段刷新物化视图避免高峰期的资源争抢。生产环境使用并发刷新如果应用在刷新期间仍需读取视图数据始终使用{ concurrently: true }前提是视图上有唯一索引保证刷新过程中读不阻塞。监控视图体积物化视图会持续占用磁盘空间且每次刷新都是全量重建REFRESH会锁表或通过并发刷新渐进重建。需监控其大小数据量极大时考虑分区策略或其他降级方案。总结MikroORM 将 PostgreSQL 物化视图建模为一种特殊的只读实体通过view: { materialized: true }声明用expression定义查询由 Schema Generator 负责CREATE/DROP/UPDATE含索引 diff用refreshMaterializedView()手动刷新可并发底层 SQL 由 PostgreSQL 专属 SchemaHelper 生成、平台能力由supportsMaterializedViews()统一管控。结合 tests/features/view-entities/view-entities.postgres.test.ts 与 tests/features/schema-generator/materialized-view-diffing.postgres.test.ts 两组测试可以完整验证定义 → 建库 → 填充数据 → 刷新 → 查询的闭环。合理使用物化视图能在保持 MikroORM 统一实体模型的同时为读多写少、容忍延迟的聚合查询带来稳定的性能收益。赞分享后端【免费下载链接】mikro-ormTypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, MariaDB, MS SQL Server, PostgreSQL and SQLite/libSQL databases.项目地址https://gitcode.com/gh_mirrors/mi/mikro-orm点击查看免费下载相关推荐在 MikroORM 中定义与刷新 PostgreSQL 物化视图Materialized Views实体在 MikroORM 中定义与刷新 PostgreSQL 物化视图Materialized Views实体 物化视图Materialized View将后端跨平台文本编辑器 Notepad-- 5 步跑通目录搜索与文件对比跨平台文本编辑器 Notepad 5 步跑通目录搜索与文件对比 你手头有一整目录散落的代码和配置改一处要翻遍几十上百个文件Notepad 帮你在一个窗口里搜桌面应用Materialized Viewpybind11物化视图性能优化实战Materialized Viewpybind11物化视图性能优化实战 引言当Python遇见C的性能瓶颈 在现代科学计算和机器学习应用中Python开发工具上一篇Cubiomes Viewer使用教程Minecraft种子查找与地图分析的终极指南下一篇VS Code十六进制编辑器完整指南从零开始搞定二进制文件查看与编辑创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
从智能遥控器到环境智能:如何让家居系统真正懂你 半夜两点半,我被自己的起夜需求叫醒,摸黑踢到拖鞋,对着卧室喊了一声“关灯”。智能音箱倒是利索地执行了,但同时也把投影仪、床头氛围灯和电视背景墙的光带全部关掉了。我盯着黑屏的投影仪愣了几秒,确认自己买的不是“… · 2026/9/26 3:07:35
BunnyScholar文献综述免费额度怎么用:邀请规则与引用核对 BunnyScholar文献综述免费额度怎么用:邀请规则与引用核对每到毕业季或者期末论文周,学生党们总是最忙碌也是最“贫穷”的群体。面对那些动辄几十上百块的查重费、降重费,很多同学只能精打细算。而在写文献综述这个耗时耗力的环节,… · 2026/9/26 3:07:35
使用 Amazon S3 托管 Squirrel.Windows 发布文件:从存储桶搭建到自动化更新分发 开发工具 【免费下载链接】Squirrel.Windows An installation and update framework for Windows desktop apps 项目地址: https://gitcode.com/gh_mirrors/sq/Squirrel.Windows 点击查看 免费下载 Amazon S3 是托管 Squirrel.Windows 发布与更新文件最简单、最经济… · 2026/9/26 3:07:29
OpenClaw大模型API怎么选?DeepSeek与Kimi配置实战:TaoToken统一Key接入 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 3:57:26
win11部署OpenClaw实测:Node.js、git、npm 环境一次跑通 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 3:57:26
【C/C++学习】inline 【C/C学习】inline 最近在学内核相关的书籍,其中一个关键字,对于它的理解不够深入,只知道它可以用于消除函数调用和返回带来的开销,但是发现它的存在不止于此 文章目录【C/C学习】inline整个总结inline是什么inline不一定保证函数… · 2026/9/26 3:57:26
Raven如何实现主动提醒还不打扰:Sentinel主动性引擎五层防线拆解 Raven如何实现主动提醒还不打扰:Sentinel主动性引擎五层防线拆解 【免费下载链接】Raven The Harness of Harnesses: a trusted, persistent, self-evolving multi-agent ecosystem for all-domain collaboration. 项目地址: https://gitcode.com/gh_mirrors/rave… · 2026/9/26 3:57:20
AI 相关认证考试全景对比(国内 + 国际)· 2026年9月版 AI 相关认证考试全景对比(国内 国际)
覆盖厂商技术认证、国家职业技能等级、行业培训证书,以及国际云厂商与治理合规类认证。
信息核实时间:2026-09-25 价格与政策随时可能调整,最终以各官方报名页面为准
一、先分… · 2026/9/26 3:57:20
纤维混凝土细观模型全流程解析:从随机骨料生成到ABAQUS实操 纤维混凝土这个东西,做实验的人多,做数值模拟的人这几年也明显多了起来。但实验只能告诉你最终结果——承载力多高、裂缝长什么样、破坏模式有多大差别,中间那些微观机制(纤维怎么桥接裂缝、怎么被拔出、基体怎么开裂的࿰… · 2026/9/26 3:57:20
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46