trismegiste/yuurei

此包已废弃,不再维护。作者建议使用trismegiste/strangelove-bundle包。

无模式的MongoDB对象文档映射器

v2.3.2 2015-08-04 07:56 UTC

This package is not auto-updated.

Last update: 2022-04-12 09:28:09 UTC


README

Yo dawg Xzibit

MongoDB中的原子性由Xzibit解释

什么是

这是一个具有自动映射的微型数据库层。它适用于熟悉并理解无模式数据库上模型增长的MongoDB的高级用户。

当我提到“微型”时,意味着NCLOC的总和小于臭名昭著的方法UnitOfWork::createEntity在Doctrine 2中的大小

当然,功能也是“微型”。不要期望不可能的事情。尽管如此,还有一些你可能在其他地方找不到的功能。

此外,此DBAL可以完全扩展。我的其他存储库DokudokiBundle为symfony2添加了3种额外的映射系统,而无需编写大量代码。

如何

像其他PHP包一样使用Composer

 $ composer.phar require trismegiste/yuurei dev-master

为什么

因为,就像蛋糕一样,“ODM是一个谎言”。将MongoDB转换成类似ORM的抽象是最糟糕的事情,你可以在NoSQL数据库上做的事情。

使用ODM,你失去了NoSQL和RDBMS的特性,以下是一些

  • MongoDB没有丰富的文档,因为查询生成器很糟糕,映射很复杂
  • 没有无模式的能力,因为你在类中冻结了模型
  • 没有JOIN,你必须依赖于缓慢的延迟加载
  • 没有RDBMS的约束(引用和类型),因为没有这些
  • 没有原子性:MongoDB中唯一的原子性是在一个文档上

事实上,ODM是一个缓慢的ORM,没有ACID:使用MongoDB的目的是什么?

这就是为什么我停止追逐“神秘的对象数据库”,并开始破解。

指导

  • 丰富的文档由地狱!你有原子性。
  • 停止思考1个实体 <=> 1个表
  • 只有少量根实体:2、3或4个,最多10个用于完整的电子商务应用,而不是200个!
  • 1个应用 <=> 1个集合
  • 忘记1NF、2NF和3NF。在MongoDB中处理反规范化数据比在MySQL中进行过多的LEFT JOIN更容易
  • 像serialize/unserialize一样思考
  • 不要试图用你的数据库创建搜索引擎:使用Elastic Search
  • 不要试图将所有内容存储在集合中:使用XML文件

因此,你将模型分成几个部分,没有循环引用,并将其存储起来。这就像序列化,但是在MongoDB中。

所有非静态属性都存储在一种方式中,您可以使用强大的(但坦白说非常奇怪)的MongoDB语言轻松查询。

请参阅PHPUnit测试以获取序列化过程的示例。

这就像序列化

您知道PHP可以使用序列化保存和恢复任何对象到会话中,并且不需要任何映射信息、注释或存储库。这是我开始这个库时的范式。

为什么ORM/ODM不能做同样的事情?当然,我需要一个NoSQL数据库。但这个类似dbal/odm的数据库不需要任何映射信息,存储在数据库中的对象保持其原始结构(没有太多噪音)。因此,您可以使用MongoDB进行复杂查询。

请参阅单元测试中的完整示例。

// simple object
$doc = new \Some\Sample\Product('EF-85 L', 2000);
// persisting
$this->invocation->persist($doc);
// restoring with invocation repository
$restore = $this->invocation->findByPk((string) $doc->getId());
$this->assertInstanceOf('Some\Sample\Product', $restore);
// retrieving the content in the MongoDB
$dump = $this->collection->findOne(array('_id' => $doc->getId()));
$this->assertEquals('Some\Sample\Product', $dump['-fqcn']);  // we store the FQCN
$this->assertEquals('EF-85 L', $dump['title']);
$this->assertEquals(2000, $dump['price']);

关于MDE

随着最近的NoSQL、SOA和HMVC概念,我认为MDE有些过时了,虽然不是总是这样,但非常频繁。事实上,这并不是MDE本身,而是一个非常常见的反模式:“数据库驱动开发”,其中所有源代码都来自数据库模式。结合CRUD生成器,会导致贫血模型、愚蠢的构造函数和无用的setter/getter(没有业务意义)。

关于性能

待办

常见问题解答

有什么要求?

  • PHP >= 5.4
  • PECL Mongo扩展 >= 1.3

如何映射属性?

所有对象的属性都将被存储。您只需做一件事:根类必须实现Persistable接口(有一个特质用于实现此接口)。您不需要扩展任何特定类,因此您可以在没有约束的情况下遵循DDD。

什么是“根类”?

这是存储在集合中、其键为'_id'的MongoId的类。此类中的所有其他聚合对象不需要实现Persistable,它们将被递归存储。

有什么约束?

此库无法保存和恢复来自父类的私有属性。持久化类中的私有属性是好的,但它们不会被子类看到,因此如果您将这些子类保存到数据库中,则无法持久化。这是一个很大的限制,所以使用关键字'private'时要小心。

我如何删除一些瞬态属性?

您不能。但您可以使用具有Skippable接口的瞬态类。使用装饰者模式或状态模式。您的模型可以做到这一点。

我可以在持久化之前进行一些清理吗?

类似于序列化,您可以通过实现两个方法来实现Cleanable:唤醒和睡眠。

如何查询列表?

使用MongoCollection,您无法比这个底层层更高效。

如何存储图片或PDF?

在您的模型中使用MongoBinData,它以原样存储。

我可以用MongoId以外的其他东西作为主键吗?

不。当然,MongoDB允许您使用其他内容,但在大多数情况下,这并不是一个好主意。

关于MongoDate呢?

任何DateTime都将转换为MongoDate,反之亦然。

您对这个库使用了哪些指导原则?

  • 除了一个接口(用于DDD关注点)之外,模型没有强制性的继承。
  • 最小数量的switch,因为它是隐藏的继承。
  • 每个类不超过5个方法。
  • 没有方法超过20 NCLOC。
  • 没有静态方法,因为它是全球性的。
  • SRP, OCP, LSP, ISP, DIP 保持在最高水平
  • 耦合度保持在最低水平(通过Mondrian 检查)

对于DBRef是否有任何延迟加载或代理类?

飞吧,傻瓜们

“幽霊”的含义是什么?

实际上,这个库是DokudokiBundle的一部分,我想保留这个Bundle中最好的部分,作为一个独立的库。因此,我保留了它的日文名称。幽霊意味着鬼魂或精神,因为在原始的bundle中,这个映射系统被命名为“Invocation”。