后端【免费下载链接】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 的 JSON 属性功能允许你在关系型数据库中直接存储、查询和索引任意 JSON 结构同时保持 TypeScript 的类型安全。本文将围绕官方文档 json-properties.md 展开深入讲解如何定义 JSON 属性、如何按对象属性嵌套查询、如何使用$elemMatch匹配数组元素以及如何在 JSON 路径上创建普通/唯一/复合索引并结合仓库源码揭示其底层实现原理。读完本文你将能够在 PostgreSQL、MySQL、MariaDB、SQLite 与 MongoDB 等支持的数据库中熟练使用 MikroORM 的 JSON 查询能力并理解查询 SQL 是如何生成的。定义 JSON 属性不同数据库驱动对 JSON 的处理方式差异很大有些驱动会自动解析 JSON 值并返回 JS 对象另一些则原样返回 JSON 字符串。为了统一这种体验MikroORM 通过JsonType类型封装了序列化与反序列化逻辑当你指定type: json时ORM 也会自动使用该类型。在实体中定义 JSON 属性非常简单Entity() export class Book { Property({ type: json, nullable: true }) meta?: { foo: string; bar: number }; }这里meta的 TypeScript 类型直接描述了 JSON 结构MikroORM 无需额外的 schema 声明即可在读写时完成对象与数据库字符串之间的转换。JsonType 的底层实现从源码看JsonType继承自Type基类核心逻辑位于 packages/core/src/types/JsonType.tsconvertToDatabaseValue写入时将 JS 对象交给platform.convertJsonToDatabaseValue()序列化convertToJSValue读取时判断列类型是否为json/jsonb且平台支持自动转换若支持则直接返回原始对象否则调用platform.convertJsonToJSValue()解析字符串convertToJSValueSQL/convertToDatabaseValueSQL为 SQL 层提供列级转换如 PostgreSQL 的::jsonb或::text转换getColumnType返回platform.getJsonDeclarationSQL()即各平台对应的 JSON 列声明如 PostgreSQL 的jsonb。这种设计使得同一个实体定义在不同数据库上都能正确工作无需针对驱动单独写序列化代码。官方 custom-types.md 文档也确认了这一点JsonType以驱动无关的方式处理序列化仅在必要时才调用parse和stringify。注意JsonType也常用于嵌入对象embeddable的存储其ensureComparable方法决定了该属性在查询时是否需要走 JSON 路径比较逻辑。按 JSON 对象属性查询你可以像查询普通字段一样直接按 JSON 对象的嵌套属性进行查询const b await em.findOne(Book, { meta: { valid: true, nested: { foo: 123, bar: 321, deep: { baz: 59, qux: false, }, }, }, });在 PostgreSQL 上上述条件会生成如下 SQLselect e0.* from book as e0 where (meta-valid)::bool true and meta-nested-foo 123 and (meta-nested-bar)::float8 321 and (meta-nested-deep-baz)::float8 59 and (meta-nested-deep-qux)::bool false limit 1可以看到MikroORM 将嵌套对象逐层展开为-/-路径访问并且字符串比较直接使用-取值数字会附加::float8类型转换布尔值会附加::bool类型转换。所有受支持的驱动包括 SQLite 和 MongoDB都支持这种按 JSON 对象属性查询的方式。在 PostgreSQL 上当检测到右侧值是数字或布尔值时MikroORM 会自动尝试进行类型转换以保证查询结果准确。底层处理路径当查询条件中某个属性的自定义类型是JsonType且值不是原始 SQLRaw、不是$eq/$elemMatch操作符包装时查询处理器会将其识别为 JSON 条件并交由QueryHelper.processJsonCondition()处理见 packages/core/src/utils/QueryHelper.ts。该方法最终委托给对应平台的platform.processJsonCondition()由各平台生成-/-路径表达式、类型转换与别名处理这正是不同数据库 JSON 语法差异得以统一的根源。查询 JSON 数组元素$elemMatch当 JSON 属性存储的是对象数组时你可以使用$elemMatch操作符查询满足条件的数组元素。MikroORM 会为不同平台生成相应的EXISTS子查询PostgreSQL 使用jsonb_array_elementsMySQL/MariaDB 使用json_tableSQLite 使用json_each。查询值的类型会被自动推断无需任何 schema 提示Entity() export class Event { Property({ type: json, nullable: true }) tags?: { name: string; priority: number }[]; } // 查找包含 typescript 标签的事件 const events await em.find(Event, { tags: { $elemMatch: { name: typescript } }, }); // 数值条件会被自动转换如 PostgreSQL 上的 ::float8 const events await em.find(Event, { tags: { $elemMatch: { priority: { $gt: 5 } } }, }); // 多个条件必须匹配同一个数组元素 const events await em.find(Event, { tags: { $elemMatch: { name: typescript, priority: { $gte: 8 } } }, }); // $or/$and/$not 可以在 $elemMatch 内部使用 const events await em.find(Event, { tags: { $elemMatch: { $or: [{ name: typescript }, { name: rust }] } }, });关键语义$elemMatch中的多个条件必须命中同一个数组元素而不是分散在不同元素上。这与 MongoDB 的$elemMatch语义一致也与普通$contains只要数组包含某个元素即满足形成鲜明对比。$elemMatch还可以通过$and与数组级别的操作符组合使用const events await em.find(Event, { $and: [ { tags: { $elemMatch: { priority: { $gt: 5 } } } }, { tags: { $contains: [{ name: typescript }] } }, ], });对于嵌入数组属性embeddable array由于 ORM 可以从 embeddable 元数据中获知元素结构元素级查询是隐式生效的无需显式书写$elemMatch详见 embeddables.md。$elemMatch 的源码实现$elemMatch的处理位于 packages/sql/src/query/QueryBuilderHelper.ts当条件键的$elemMatch存在且是该键的唯一操作符时会调用processJsonElemMatch()生成EXISTS子查询。该实现有两个值得注意的细节类型校验$elemMatch只能用于JsonType的数组属性。如果用在非 JSON 属性上会抛出ValidationError提示$elemMatch can only be used on JSON array properties类型推断inferJsonValueType()QueryBuilderHelper.ts根据查询值的 JS 类型推断 JSON 元素类型——number推断为number、boolean推断为boolean、bigint推断为bigint、对象内部的值也会被递归探测默认回退为string。这正是文档所述类型自动推断的实现基础也是 PostgreSQL 上生成::float8等转换的依据。$elemMatch与$contains等数组操作符组合时processObjectSubCondition会先将多操作符条件拆分使$elemMatch单独进入上述处理分支从而正确生成多个EXISTS子查询并用AND连接见 QueryBuilderHelper.ts。JSON 属性上的索引在 JSON 属性上创建索引需要使用实体级别的Index()装饰器并通过点路径dot path指定 JSON 字段Entity() Index({ properties: metaData.foo }) Index({ properties: [metaData.foo, metaData.bar] }) // 复合索引 export class Book { Property({ type: json, nullable: true }) metaData?: { foo: string; bar: number }; }在 PostgreSQL 上这会生成如下 SQLcreate index book_meta_data_foo_index on book ((meta_data-foo));创建唯一索引则使用Unique()装饰器语法与Index()完全一致Entity() Unique({ properties: metaData.foo }) Unique({ properties: [metaData.foo, metaData.bar] }) // 复合唯一索引 export class Book { // ... }MySQL 上的 JSON 索引与函数索引MySQL 不允许直接对 JSON 列建立普通索引必须借助函数索引functional index。MikroORM 支持通过options显式指定returning类型从而生成合法的 MySQL 函数索引Entity() Index({ properties: metaData.foo, options: { returning: char(200) } }) export class Book { // ... }生成的 SQL 如下alter table book add index book_meta_data_foo_index((json_value(meta_data, $.foo returning char(200))));其中json_value()是 MySQL 的 JSON 提取函数returning char(200)指定了索引列的返回类型。需要注意MariaDB 驱动目前不支持此特性json_value函数索引语法无法在 MariaDB 上生成。实践建议在 PostgreSQL 上优先使用jsonb列类型配合点路径索引可以在按 JSON 字段过滤时获得索引加速对于高频查询的 JSON 字段复合索引多个点路径能进一步提升组合过滤性能但索引大小会随之增加需权衡MySQL 上必须为索引提供returning类型否则无法生成合法的函数索引该选项在不同 MySQL 版本上的兼容性需结合目标实例验证。小结MikroORM 的 JSON 支持是一条完整的链路JsonType统一了各驱动的序列化差异type: json即可声明 JSON 属性查询层通过platform.processJsonCondition()生成平台相关的-/-路径表达式并自动做类型转换$elemMatch通过EXISTS子查询实现数组元素级过滤类型自动推断免去了 schema 声明索引层则支持点路径的普通/唯一/复合索引并在 MySQL 上通过returning生成函数索引。掌握这些能力你就可以在保持类型安全的前提下把灵活的 JSON 结构无缝融入关系型数据库的工作流中。赞分享后端【免费下载链接】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 JSON 属性实战指南定义、查询、$elemMatch 与索引MikroORM JSON 属性实战指南定义、查询、$elemMatch 与索引 导读 本文是 MikroORM 官方文档 JSON Properties h后端MikroORM JSON 属性完全指南定义、对象查询、$elemMatch 数组查询与 JSON 索引MikroORM JSON 属性完全指南定义、对象查询、$elemMatch 数组查询与 JSON 索引 MikroORM 为 Node.js 提供了一套跨数后端MikroORM JSON 属性实战指南定义、查询、$elemMatch 与索引MikroORM JSON 属性实战指南定义、查询、$elemMatch 与索引 本篇技术指南围绕 MikroORM基于 Data Mapper、Unit后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考