MongoDB
目前,MongoDB
并沒有提供協程版本的 php
客戶端,只有同步阻塞版本。
EasySwoole 的協程版客戶端已經在排期內。
在實際生產中,直接創建原生的 MongoDB客戶端
來進行數據交互,也不是不可。
若希望將同步調用轉為協程調用,可以用 Easyswoole
提供的 sync-invoker
組件。
將 MongoDB客戶端
的同步調用轉為協程調用具體使用如下:
定義驅動
<?php
namespace App\MongoDb;
use EasySwoole\EasySwoole\Trigger;
use EasySwoole\SyncInvoker\AbstractDriver;
use MongoDB\Client;
class Driver extends AbstractDriver
{
private $db;
// 【建議使用】
// 使用 mongodb/mongodb composer組件包封裝的 MongoDB 客戶端調用類,作為客戶端調用驅動
// 【前提:需要先使用 `composer require mongodb/mongodb` 安裝 mongodb/mongodb composer組件包】
function getDb(): Client
{
if ($this->db == null) {
// 這里為要連接的 mongodb 的服務端地址【前提是必須先有服務端,且安裝 php-mongodb 擴展才可使用】
$mongoUrl = "mongodb://127.0.0.1:27017";
$this->db = new Client($mongoUrl);
}
return $this->db;
}
// 僅使用 php-mongodb 擴展內置類(不使用composer組件包的),作為客戶端調用驅動
/*
function getDb(): \MongoDB\Driver\Manager
{
if ($this->db == null) {
// 這里為要連接的 mongodb 的服務端地址【前提是必須先有服務端,且安裝 php-mongodb 擴展才可使用】
$mongoUrl = "mongodb://127.0.0.1:27017";
$this->db = new \MongoDB\Driver\Manager($mongoUrl);
}
return $this->db;
}
*/
protected function onException(\Throwable $throwable)
{
Trigger::getInstance()->throwable($throwable);
return null;
}
}
客戶端調用類定義
<?php
namespace App\MongoDb;
use EasySwoole\Component\Singleton;
use EasySwoole\SyncInvoker\SyncInvoker;
class MongoClient extends SyncInvoker
{
use Singleton;
}
注冊 Invoker 服務
在 EasySwoole 全局事件
的 mainServerCreate 事件
中進行服務注冊
<?php
namespace EasySwoole\EasySwoole;
use EasySwoole\EasySwoole\AbstractInterface\Event;
use EasySwoole\EasySwoole\Swoole\EventRegister;
class EasySwooleEvent implements Event
{
public static function initialize()
{
// TODO: Implement initialize() method.
date_default_timezone_set('Asia/Shanghai');
}
public static function mainServerCreate(EventRegister $register)
{
// 配置 Invoker
$invokerConfig = \App\MongoDb\MongoClient::getInstance()->getConfig();
$invokerConfig->setDriver(new \App\MongoDb\Driver()); // 配置 MongoDB 客戶端協程調用驅動
// 以下這些配置都是可選的,可以使用組件默認的配置
/*
$invokerConfig->setMaxPackageSize(2 * 1024 * 1024); // 設置最大允許發送數據大小,默認為 2M【注意:當使用 MongoDB 客戶端查詢大于 2M 的數據時,可以修改此參數】
$invokerConfig->setTimeout(3.0); // 設置 MongoDB 客戶端操作超時時間,默認為 3.0 秒;
*/
// 注冊 Invoker
\App\MongoDb\MongoClient::getInstance()->attachServer(ServerManager::getInstance()->getSwooleServer());
}
}
在框架中使用 MongoDB 客戶端(協程調用)
<?php
namespace App\HttpController;
use App\MongoDb\Driver;
use App\MongoDb\MongoClient;
use EasySwoole\Http\AbstractInterface\Controller;
use EasySwoole\Utility\Random;
class Index extends Controller
{
public function index()
{
// 使用 mongodb/mongodb composer組件包【建議使用,需要先使用composer安裝】
$ret = MongoClient::getInstance()->invoke()->callback(function (Driver $driver) {
$ret = $driver->getDb()->user->list->insertOne([
'name' => Random::character(8),
'sex' => 'man',
]);
if (!$ret) {
$driver->response(false);
}
$driver->response($ret->getInsertedId());
});
var_dump($ret);
$ret = MongoClient::getInstance()->invoke()->callback(function (Driver $driver) {
$ret = [];
$collections = $driver->getDb()->user->listCollections();
foreach ($collections as $collection) {
$ret[] = (array)$collection;
}
$driver->response($ret);
});
var_dump($ret);
/**
* 輸出結果:
* object(MongoDB\BSON\ObjectId)#109 (1) {
["oid"]=>
string(24) "600da377004c82305a02fb52"
}
* array(1) {
[0]=>
array(1) {
["MongoDB\Model\CollectionInfoinfo"]=>
array(5) {
["name"]=>
string(4) "list"
["type"]=>
string(10) "collection"
["options"]=>
array(0) {
}
["info"]=>
array(2) {
["readOnly"]=>
bool(false)
["uuid"]=>
object(MongoDB\BSON\Binary)#110 (2) {
["data"]=>
string(16) "EasySwoole"
["type"]=>
int(4)
}
}
["idIndex"]=>
array(4) {
["v"]=>
int(2)
["key"]=>
array(1) {
["_id"]=>
int(1)
}
["name"]=>
string(4) "_id_"
["ns"]=>
string(9) "user.list"
}
}
}
}
*/
// 使用 php-mongodb 擴展時(不使用 mongodb/mongodb composer組件包)
/*
// 插入數據
$rets = MongoClient::getInstance()->invoke()->callback(function (Driver $driver) {
$bulk = new \MongoDB\Driver\BulkWrite();
$bulk->insert([
'name' => Random::character(8),
'sex' => 'man',
]);
$bulk->insert(['_id' => 1, 'x' => 1]);
$bulk->insert(['_id' => 2, 'x' => 2]);
$bulk->update(['x' => 2], ['$set' => ['x' => 1]], ['multi' => false, 'upsert' => false]);
$bulk->update(['x' => 3], ['$set' => ['x' => 3]], ['multi' => false, 'upsert' => true]);
$bulk->update(['_id' => 3], ['$set' => ['x' => 3]], ['multi' => false, 'upsert' => true]);
$bulk->insert(['_id' => 4, 'x' => 2]);
$bulk->delete(['x' => 1], ['limit' => 1]);
$manager = $driver->getDb();
$writeConcern = new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY, 100);
// 查到 user 庫的 list 集合中
$ret = $manager->executeBulkWrite('user.list', $bulk, $writeConcern);
printf("Inserted %d document(s)\n", $ret->getInsertedCount()); // 插入條數
printf("Matched %d document(s)\n", $ret->getMatchedCount()); // 匹配條數
printf("Updated %d document(s)\n", $ret->getModifiedCount()); // 修改條數
printf("Upserted %d document(s)\n", $ret->getUpsertedCount()); // 修改插入條數
printf("Deleted %d document(s)\n", $ret->getDeletedCount()); // 刪除條數
foreach ($ret->getUpsertedIds() as $index => $id) {
printf('upsertedId[%d]: ', $index);
var_dump($id);
}
if (!$ret) {
return false;
}
return true;
});
// 查詢數據
$rets = MongoClient::getInstance()->invoke()->callback(function (Driver $driver) {
$filter = ['x' => ['$gt' => 1]];
$options = [
'projection' => ['_id' => 0],
'sort' => ['x' => -1],
];
// 查詢數據
$query = new \MongoDB\Driver\Query($filter, $options);
$cursor = $driver->getDb()->executeQuery('user.list', $query);
foreach ($cursor as $document) {
print_r($document);
}
});
*/
}
}