jpc/mongodb-odm

一个小巧的MongoDB ODM

1.3.1 2019-04-18 07:01 UTC

README

JPC\MongoDB-ODM 是一个智能的 MongoDB-PHP 映射器。它允许您将 PHP 对象映射到 MongoDB 文档中。此库支持最新的 mongodb 驱动程序,可在以下链接找到:这里

有关更多详细信息,请参阅 'doc' 文件夹。

安装

使用 Composer 安装

在您的控制台终端

php composer.phar require jpc/mongodb-odm:^1.3

或在您的 composer.json 文件中

{
    "require" : {
        "jpc/mongodb-odm" : "^1.3"
    }
}

创建映射类

您的类

要使用 MongoDB-ODM,您需要将您的类视为一个 mongoDb 文档,并定义您所需的内容

  • 一个 id
  • 一些字段

您可以创建一个简单的对象,如下所示

<?php

namespace ACME\Model;

class MyDoc {

	private $id;

	private $field1

	private $field2;

	//GETTERS AND SETTERS
}

好了,您已经有了您的类。现在您必须告诉 MongoDB-ODM 哪个属性对应哪个字段,以及哪个集合文档(和将要存储的文档)

映射

为此,MongoDB-ODM 使用注解。在 JPC\MongoDB\ODM\Annotations\Mapping 中有一些基本的注解,可以用于创建映射

  • Document:定义集合信息
  • Id:定义将匹配 mongoDb _id 字段的属性
  • Field:定义字段映射

现在,按照如下方式编辑您的对象

<?php

namespace ACME\Model;

use JPC\MongoDB\ODM\Annotations\Mapping as ODM;

/**
 * @ODM\Document("my_collection")
 */
class MyDoc {

	/**
	 * @ODM\Id
	 */
	private $id;

	/**
	 * @ODM\Field('my_first_field')
	 */
	private $field1

	/**
	 * @ODM\Field('my_second_field')
	 */
	private $field2;

	//GETTERS AND SETTERS
}

高级映射

好了,您有一个简单的文档,但它仍然缺少一些东西...也许像嵌入式文档这样的东西。别担心,MongoDB-ODM 支持!

创建嵌入式类

<?php

namespace ACME\Model;

use JPC\MongoDB\ODM\Annotations\Mapping as ODM;

class MyEmbedded {

	/**
	 * @ODM\Field('one_field_emb')
	 */
	private $oneFieldEmb

	/**
	 * @ODM\Field('two_field_emb')
	 */
	private $twoFieldEmb;

	//GETTERS AND SETTERS
}

现在,您可以使用两个注解在先前的类中添加嵌入式文档

  • EmbeddedDocument:嵌入指定类型的文档
  • MultiEmbeddedDocument:嵌入指定类型的文档数组

按照如下方式修改类 MyDoc

<?php

namespace ACME\Model;

use JPC\MongoDB\ODM\Annotations\Mapping as ODM;

/**
 * @ODM\Document("my_collection")
 */
class MyDoc {

	/**
	 * @ODM\Id
	 */
	private $id;

	/**
	 * @ODM\Field('my_first_field')
	 */
	private $field1

	/**
	 * @ODM\Field('my_second_field')
	 */
	private $field2;

	/**
	 * @ODM\Field('my_embedded_document')
	 * @ODM\EmbeddedDocument('ACME\Model\MyEmbedded')
	 */
	private $myEmbedded;

	//GETTERS AND SETTERS
}

获取文档

获取文档管理器

您可以使用库中提供的工厂轻松地创建文档管理器。

工厂有一个名为 createDocumentManager 的方法,该方法接受 mongo uri 作为第一个参数,数据库名称作为第二个参数。

现在,创建一个文档管理器

<?php

use JPC\MongoDB\ODM\Factory\DocumentManagerFactory;

$factory = new DocumentManagerFactory();
$factory->createDocumentManager("mongodb://user:password@myserver.com:27017/authdb", "my_db");

获取仓库

现在,您需要获取仓库。仓库将允许您从 MongoDB 获取文档。

要获取仓库,请使用文档管理器的 getRepository 方法。

这是该方法

public function getRepository($modelName, $collection = null)

如果 $collection 为 null,MongoDB-ODM 将使用模型中设置的 Document 注解中的集合

在我们的案例中(在 2-创建映射类 中配置的模型)

<?php

[...]

$repository = $documentManager->getRepository("ACME\Model\MyDoc");

现在,您可以通过使用仓库的这些函数之一简单地查找文档(有关方法的更多信息,请参阅方法声明)

public function find($id, $projections = [], $options = []);
public function findAll($projections = [], $sorts = [], $options = []);
public function findBy($filter, $projections = [], $sorts = [], $options = []);
public function findOneBy($filter = [], $projections = [], $sorts = [], $options = []);
public function findAndModifyOneBy($filter = [], $update = [], $projections = [], $sorts = [], $options = []);

示例

<?php

[...]

$repository = $documentManager->getRepository("ACME\Model\MyDoc");

// NOTE: filter, projections, etc... can be property name or field name
$myDocument = $repository->findOneBy(["field1" => "my_field_value", "myEmbedded.oneFieldEmb" => "another_value"]);

插入、更新或删除文档

插入文档

首先,您必须创建您的对象并在其中插入数据

$obj = new MyDoc();
$obj->setField1("MyValue");
$obj->setField2("MySecondValue");

很好!现在我们想要将其存储在数据库中。为此,您必须告诉 MongoDB-ODM 您的对象需要由它管理。这里的 manage 意味着 MongoDB-ODM 将查看是否需要插入、更新或删除您的对象。

所以,要这样做,您需要 persist 您的对象。

这是文档管理器的 persist 函数

public function persist($object, $collection = null);

对于我们的对象

$documentManager->persist($obj);

下一步是告诉 MongoDB-ODM 需要保存所有管理对象的所有更改。为此,有一个名为 flush 的函数,只需调用它即可。

$documentManager->flush();

检查你的 mongoDb 集合,如果它是空的,你可能犯了一个错误 😕

更新文档

想象一下,你的集合中有许多文档,你只想更新其中的一些。

首先,你必须获取你想要的文档,如下所示

$repo = $documentManager->getRepository("ACME\Model\MyDoc");
$docs = $repo->findBy(["field_1" => "value"])

注意:如果你使用 persistflush 插入了一个文档,它已经准备好更新,你不需要再次从仓库中获取它

现在对它们进行一些修改

foreach($docs as $index => $doc){
	$doc->setField2($index);
}

这是一个非常棒的修改 😉

现在你只需要 flush

注意:从仓库中找到的对象已经持久化,你不需要再次持久化

$documentManager->flush();

删除文档

删除就像更新一样简单

从仓库获取你的文档,然后告诉文档管理器要删除它们并刷新

foreach($docs as $doc){
	$documentManager->remove($doc);
}

$documentManager->flush();

附加信息

使用 MongoDB-ODM 更新的优点

使用 MongoDB-ODM 进行更新的优点是它只会更新修改过的字段,而不是整个对象。

取消持久化

如果你在代码中对已持久化的对象进行了一些修改,并且你不想在下次刷新时存储更改,你可以使用 unpersist 函数取消持久化

$documentManager->unpersist($obj);

如果你想取消持久化所有对象,请使用 clear

$documentManager->clear();

GridFS 文档

为 GridFS 文档创建映射

你的类需要继承类 JPC\MongoDB\ODM\GridFS\Document。该类定义了 GridFS 文档的所有默认字段,如 md5filename 等。有关更多详细信息,请参阅此类。

要向你的文档添加元数据,你需要使用 Metadata 注解。

以下是一个示例

namespace ACME\Model;

use JPC\MongoDB\ODM\Annotations\Mapping as ODM;
use JPC\MongoDB\ODM\GridFS\Annotations\Mapping as GFS;
use JPC\MongoDB\ODM\GridFS\Document;

/**
 * @GFS\Document("my_gridfs_bucket")
 */
class MyGridFSDoc extends Document {

    /**
     * @ODM\Field('my_meta_1')
     * @GFS\Metadata
     */
    private $meta1;

}

请注意,类 Document 注解是由 GFS 而不是由 ODM 命名空间提供的

插入文档

在 GridFS 中插入文档就像在基本 mongoDB 集合中插入文档一样。

以下是一个完整的示例

$doc = new MyGridFSDoc();
$doc->setId("my_super_id")
$doc->setFilename("my_file.txt");
$doc->setContentType("text/plain");
$doc->setMeta1("my_value");
$doc->setStream(fopen("my_file.txt", 'r'));

$documentManager->persist($doc);
$documentManager->flush();

集合选项

集合选项

当你创建模型时,你可以在 Document 注解中指定更多关于模型的信息

<?php

namespace ACME\Model;

use JPC\MongoDB\ODM\Annotations\Mapping as ODM;

/**
 * @ODM\Document(
 *      "my_collection",
 *      "repositoryClass"="MyCustomRepositoryClass",
 *      "hydratorClass"="MyCustomHydratorClass",
 *      "capped"=true,
 *      "size"=536900000,
 *      "max"=1000
 * )
 */
class MyDoc {
    //...
}

并且你可以使用 Option 注解设置 ReadConcern、ReadPreference、TypeMap 和 WriteConcern(别忘了使用)

<?php

namespace ACME\Model;

use JPC\MongoDB\ODM\Annotations\Mapping as ODM;
use JPC\MongoDB\ODM\Annotations\CollectionOption as CO;

/**
 * @ODM\Document(//...)
 * @ODM\Option(
 *      readConcern=@CO\ReadConcern("local"),
 *      readPreference=@CO\ReadPreference(
 *          \MongoDB\Driver\ReadPreference::RP_PRIMARY_PREFERRED,
 *          tagset={{"dc"="ny"}}
 *      ),
 *      typeMap={
 *          "root"="array",
 *          "array"="array",
 *          "document"="array"
 *      },
 *      writeConcern=@CO\WriteConcern(
 *          w="majority",
 *          timeout=500,
 *          journal=false
 *      )
 * )
 */
class MyDoc {
    //...
}

事件

可用事件

如何使用

要向你的模型类添加事件,你需要告诉 ODM 你想要使用一些事件,通过使用 HasLifecycleCallbacks 注解

<?php

namespace ACME\Model;

use JPC\MongoDB\ODM\Annotations\Mapping as ODM;
use JPC\MongoDB\ODM\Annotations\Event;

/**
 * @ODM\Document("my_collection")
 * @Event\HasLifecycleCallbacks
 */
class MyDoc {
    //...
}

现在你可以添加一些带有事件注解的方法

<?php

namespace ACME\Model;

use JPC\MongoDB\ODM\Annotations\Mapping as ODM;
use JPC\MongoDB\ODM\Annotations\Event;

/**
 * @ODM\Document("my_collection")
 * @Event\HasLifecycleCallbacks
 */
class MyDoc {
    //...

    /**
     * @Event\PreFlush
     */
    public function updateTimestamp(){
        $this->date = time();
    }
}