
后端【免费下载链接】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基于 Data Mapper、Unit of Work 与 Identity Map 模式的 TypeScript ORM中JSON 属性的完整使用链路展开从实体中定义 JSON 字段、按 JSON 对象属性查询、对 JSON 数组使用$elemMatch到为 JSON 属性创建索引内容以 docs/versioned_docs/version-5.9/json-properties.mdv5.9 版本文档为主体骨架并结合当前仓库packages/core与packages/sql的源码实现进行纵深印证。读完本文你将能直接在项目中使用type: json字段并写出跨 PostgreSQL / MySQL / MariaDB / SQLite / MongoDB / MSSQL 等驱动统一语义的 JSON 查询。定义 JSON 属性不同数据库驱动对 JSON 列的处理方式差异很大有些驱动如 MongoDB、PostgreSQL 的jsonb会自动把查询结果解析为 JavaScript 对象另一些驱动则返回 JSON 字符串。MikroORM 通过统一的 JsonTypeTypeunknown, string | null来抹平这些差异——只要在Property中指定type: jsonORM 就会自动选用该类型。Entity() export class Book { Property({ type: json, nullable: true }) meta?: { foo: string; bar: number }; }从 JsonType 源码可以看到它的核心职责convertToDatabaseValue写入数据库时把 JS 对象交给platform.convertJsonToDatabaseValue序列化convertToJSValue读取时先判断当前驱动是否convertsJsonAutomatically()见 Platform.ts默认返回true如果驱动本身已自动解析 JSON 列就直接返回原值避免重复JSON.parsegetColumnType列类型统一交给platform.getJsonDeclarationSQL()例如 PostgreSQL 平台返回jsonb见 BasePostgreSqlPlatform.ts其余驱动默认是json。按 JSON 对象属性查询该能力自 v4.4.2 起加入v5.9 完全支持。可以在findOne/find的查询条件中直接使用嵌套对象匹配 JSON 内部结构const b await em.findOne(Book, { meta: { valid: true, nested: { foo: 123, bar: 321, deep: { baz: 59, qux: false, }, }, }, });在 PostgreSQL 上会生成如下 SQL路径逐层用-/-展开字符串取文本、数字与布尔值自动加类型转换select 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该能力目前覆盖所有驱动包括 SQLite 与 MongoDB。在 PostgreSQL 上当右侧值为 number 或 boolean 时ORM 会尝试对提取结果做类型转换。这条查询链路的底层实现在 QueryHelper.ts当属性是JsonType且条件值是普通对象非$eq/$elemMatch开头时会调用processJsonCondition递归地把每个键展开成 JSON 路径随后各平台通过getSearchJsonPropertyKey生成具体 SQL 片段。以 PostgreSQL 为例BasePostgreSqlPlatform.ts字符串类型的叶子用-取文本数字 / 布尔值通过#jsonTypeCasts映射表生成::float8、::bool等显式转换路径中间层用-连接键名一律安全引用防止 SQL 注入。使用$elemMatch查询 JSON 数组元素当 JSON 属性存放的是对象数组时可用$elemMatch操作符针对数组中的单个元素属性做查询。MikroORM 会生成EXISTS子查询并针对各平台选择对应的 JSON 数组展开函数PostgreSQL 用jsonb_array_elements、MySQL/MariaDB 用json_table、SQLite 用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 } }, }); // 数值条件自动完成类型转换如 postgres 上的 ::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还可以通过$and与数组级操作符组合使用const events await em.find(Event, { $and: [ { tags: { $elemMatch: { priority: { $gt: 5 } } } }, { tags: { $contains: [{ name: typescript }] } }, ], });对于嵌入数组属性由于 ORM 已从 embeddable 元数据中获知元素 schema元素级查询可以隐式进行无需显式$elemMatch。仓库中的端到端测试 tests/features/embeddables/json-elem-match.test.ts 在 sqlite / mysql / mariadb / postgresql / mssql / oracledb 六种驱动上统一验证了该行为关键结论包括EXISTS语义tags为null或空数组的事件不会命中由EXISTS子查询天然处理同元素约束{ name: typescript, priority: { $lt: 3 } }这类跨条件组合要求同一元素同时满足——测试中typescript的 priority 为 10因此返回 0 条$not否定$elemMatch: { $not: { name: typescript } }匹配至少含一个非 typescript 标签的事件安全防护在非 JSON 属性上使用$elemMatch会抛错包含x; DROP TABLE event --这类非法属性名的查询会抛出Invalid JSON property name键名均被安全引用safely quoted不存在注入风险。源码层面QueryHelper.ts 在判定 JSON 条件时把$eq/$elemMatch排除在普通对象之外从而让它们走常规操作符处理路径DatabaseDriver.ts 则显式允许$exists、$ne、$eq、$elemMatch、$all作为 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 上生成的索引 DDL 大致如下create index book_meta_data_foo_index on book ((meta_data-foo));唯一索引使用Unique()装饰器写法一致Entity() Unique({ properties: metaData.foo }) Unique({ properties: [metaData.foo, metaData.bar] }) // 复合唯一索引 export class Book { Property({ type: json, nullable: true }) metaData?: { foo: string; bar: number }; }MySQL 上还可以通过options显式指定生成表达式returning char(200)用于控制表达式索引的返回类型Entity() Index({ properties: metaData.foo, options: { returning: char(200) } }) export class Book { Property({ type: json, nullable: true }) metaData?: { foo: string; bar: number }; }生成的 DDL 如下alter table book add index book_meta_data_foo_index((json_value(meta_data, $.foo returning char(200))));注意MariaDB 驱动不支持该特性。索引生成同样由平台层实现支撑Platform.getJsonIndexDefinitionPlatform.ts的默认实现原样返回列名PostgreSQL 平台覆写该方法BasePostgreSqlPlatform.ts把metaData.foo这样的点路径转换为(meta_data-foo)表达式索引路径中间层用-、叶子用-与查询条件的生成规则保持一致。总结与适用边界定义 JSON 字段统一使用Property({ type: json })由JsonType 各平台getJsonDeclarationSQL决定实际列类型PostgreSQL 为jsonb按 JSON 对象属性查询时嵌套对象会被自动展平为路径表达式PostgreSQL 会对 number / boolean 做类型转换JSON 数组查询使用$elemMatch多条件命中同一元素支持$or/$and/$not/$in可与$contains等数组级操作符通过$and组合索引与唯一索引通过实体级Index/Unique 点路径声明MariaDB 驱动除外本文示例以 v5.9 文档为准$elemMatch与 JSON 索引相关能力在后续版本v6/v7中持续演进可在 docs/docs/json-properties.md 查阅最新版本文档。赞分享后端【免费下载链接】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 属性定义、按对象属性查询与索引实战指南MikroORM 中的 JSON 属性定义、按对象属性查询与索引实战指南 本文基于 MikroORM 6.6 版本文档 docs/versioned_doc后端如何永久保存微信聊天记录WeChatMsg开源工具完整指南如何永久保存微信聊天记录WeChatMsg开源工具完整指南 你是否曾因为换手机而丢失珍贵的聊天记录那些与家人的温馨对话、重要的商务沟通、朋友的深夜畅谈是否上一篇CANN/ge RT2运行时约束规范下一篇TorchMetrics完全指南5分钟掌握PyTorch机器学习评估利器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考