
关系型数据库也能玩NoSQLDoctrine JSON ODM混合数据模型完全入门【免费下载链接】doctrine-json-odmAn object document mapper for Doctrine ORM using JSON types of modern RDBMS.项目地址: https://gitcode.com/gh_mirrors/do/doctrine-json-odmDoctrine JSON ODM 是一款面向 PHP 生态的对象文档映射器ODM它让你可以把任意 PHP 对象直接存储到关系型数据库PostgreSQL / MySQL的 JSON、JSONB 列中。它把关系型数据库的高效查询和 NoSQL 无模式schema-less文档的灵活性结合起来让你无需额外部署 MongoDB 就能构建混合数据模型。 它解决什么问题在关系型数据库中每个字段都必须在表结构里事先定义好。可现实业务中总有一些怎么变都不定的数据电商商品的规格参数有的有颜色有的有尺寸用户个性化配置、第三方 API 返回的原始报文日志、扩展属性、表单动态字段传统方案是建一堆 EAV 表或者干脆整库迁到 MongoDB。而 Doctrine JSON ODM 给出的第三条路是主数据用传统关系映射易变数据装进 JSON 列一张表、一个数据库、一套事务鱼和熊掌兼得。对比维度纯关系模型纯 NoSQL如 MongoDBDoctrine JSON ODM 混合模型结构固定性强类型、强约束无模式灵活核心字段强约束易变字段自由事务与 Join原生支持较弱沿用关系型数据库能力查询性能高高需索引JSONB 索引后接近 NoSQL运维成本低多一套集群低就用现有数据库现代关系型数据库PostgreSQL 9.4、MySQL 5.7.8原生支持 JSON 类型查询 JSON 文档既快速又强大这正是混合模型可行的基础。⚙️ 工作原理对象到 JSON 的三步之旅Doctrine JSON ODM 的核心逻辑非常清晰主要实现在 src/ 目录下几个核心文件里序列化写库当你 persist 实体时标注为json_document类型的属性值会被交给 Symfony Serializer 处理见 src/Serializer.php 与 src/Type/JsonDocumentTypeTrait.php转换成 JSON 字符串写入数据库记录类型信息序列化时会附加一个#type字段记下每个对象的类名这是读回来能认亲的关键反序列化读库查询时 JSON 被还原成原来的 PHP 对象图——包括嵌套对象、对象数组一个都不少。整个过程对开发者是透明的你写的还是熟悉的 Doctrine ORM 实体代码数据库侧则悄悄多了一个动态 JSON 列。 快速上手三步完成 Doctrine JSON ODM 安装第一步用 Composer 安装这是官方推荐的安装方式composer require dunglas/doctrine-json-odm第二步配置框架。如果你使用 Symfony 或 API Platform不需要任何额外配置——Bundlesrc/Bundle/DunglasDoctrineJsonOdmBundle.php会自动注册json_document类型和序列化服务。第三步直接映射属性。如果是直接用 Doctrine非 Symfony只需在引导代码中手动注册类型官方 README.md 的 Install 一节提供了完整示例。 版本要求PHP 8.1Doctrine ORM 2.6 / 3.xDBAL 2.6。数据库支持 PostgreSQL 9.4 和 MySQL 5.7.8详见 composer.json。想读源码的话克隆仓库git clone https://gitcode.com/gh_mirrors/do/doctrine-json-odm 第一个示例把任意对象装进 json_document 列在实体里声明一个json_document列它就能容纳任意可序列化的 PHP 数据数组、对象、嵌套对象图全都可以。class Foo { #[Column] #[Id] #[GeneratedValue] public int $id; #[Column] public string $name; // 可以存放数组、对象、嵌套对象…… #[Column(type: json_document, options: [jsonb true])] public $misc; }用起来就像平时一样$foo new Foo(); $foo-name Foo; $foo-misc [/* 任意对象图 */]; $entityManager-persist($foo); $entityManager-flush(); // 再次读取对象原样还原 $foo $entityManager-find(Foo::class, $foo-getId());完整的实体示例Foo / Bar / Baz 对象图可以参考 tests/Fixtures/TestBundle/Entity/Foo.php端到端的用法演示在 tests/FunctionalTest.php 里。️ JSON 还是 JSONB一个关键选型JSON 类型以文本存储查询时需要解析通用兼容性好JSONB 类型二进制存储支持创建索引查询性能明显更好。PostgreSQL 用户强烈建议启用 JSONB旧版 DBAL 通过列选项options: [jsonb true]开启Doctrine DBAL 4.3 则提供了专用的jsonb_document类型src/Type/JsonbDocumentType.php声明式地直接使用#[Column(type: jsonb_document)] public $foo;有了 JSONB你还可以为文档中的字段建立数据库索引甚至用原生 SQL 调用数据库的 JSON 函数如JSON_EXTRACT对无模式文档做复杂查询。️ 进阶技巧TypeMapper 与类型别名默认情况下序列化会在 JSON 里写入类的完整命名空间作为#type。这带来两个小麻烦类改名/移动命名空间→ 存量数据需要 SQL 迁移完整类名太长→ 百万级记录时浪费存储空间。Doctrine JSON ODM 的解法是类型别名在 Symfony 配置里用短别名映射类名序列化结果变成{#type: foo, ...}这样干净的结构。内置实现见 src/TypeMapper.php实现了 src/TypeMapperInterface.php非 Symfony 项目也可以自定义 TypeMapper 传给 Serializer。最妙的是引入别名是平滑的已存的老数据依然能正确反序列化。⚠️ 常见坑与 FAQ嵌套属性改了却没触发 UPDATE这是 Doctrine 按对象引用比较变更的机制导致的。解决办法修改前先clone对象让变更检测看得见README.md 有专门说明支持的数据库PostgreSQL 9.4 与 MySQL 5.75.7.8支持嵌套对象和对象图吗支持序列化/反序列化完整保留结构想在 DQL 里用 JSON 函数可用原生 SQL 查询或安装scienta/doctrine-json-functions包在 DQL 中直接调用序列化行为要微调通过setSerializationContext/setDeserializationContext即可比如关闭斜杠转义。 什么时候该上混合数据模型✅ 适合的场景主体是稳定关系结构只有部分字段高度易变商品规格、扩展属性、动态表单需要事务一致性不想再维护一套 NoSQL 集群想在现有 PostgreSQL / MySQL 上快速获得类 NoSQL能力❌ 不太适合的场景数据整体都是无模式的那直接上 MongoDB 更合适需要跨文档的复杂关联查询和全局一致性 小结Doctrine JSON ODM 用极小的学习成本给了关系型数据库半张 NoSQL 门票一列json_document就能自由存放任意 PHP 对象图JSONB 索引还能保住查询性能。如果你正在为那些永远在变的字段头疼不妨今天就试试这个混合数据模型方案。【免费下载链接】doctrine-json-odmAn object document mapper for Doctrine ORM using JSON types of modern RDBMS.项目地址: https://gitcode.com/gh_mirrors/do/doctrine-json-odm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考