MongoDB

目前,MongoDB 并没有提供协程版本的 php 客户端,只有同步阻塞版本。

EasySwoole 的协程版客户端已经在排期内。

在实际生产中,直接创建原生的 MongoDB客户端 来进行数据交互,也不是不可。

若希望将同步调用转为协程调用,可以用 Easyswoole 提供的 sync-invoker 组件。

MongoDB客户端 的同步调用转为协程调用具体使用如下:

定义驱动

  1. <?php
  2. namespace App\MongoDb;
  3. use EasySwoole\EasySwoole\Trigger;
  4. use EasySwoole\SyncInvoker\AbstractDriver;
  5. use MongoDB\Client;
  6. class Driver extends AbstractDriver
  7. {
  8. private $db;
  9. // 【建议使用】
  10. // 使用 mongodb/mongodb composer组件包封装的 MongoDB 客户端调用类,作为客户端调用驱动
  11. // 【前提:需要先使用 `composer require mongodb/mongodb` 安装 mongodb/mongodb composer组件包】
  12. function getDb(): Client
  13. {
  14. if ($this->db == null) {
  15. // 这里为要连接的 mongodb 的服务端地址【前提是必须先有服务端,且安装 php-mongodb 扩展才可使用】
  16. $mongoUrl = "mongodb://127.0.0.1:27017";
  17. $this->db = new Client($mongoUrl);
  18. }
  19. return $this->db;
  20. }
  21. // 仅使用 php-mongodb 扩展内置类(不使用composer组件包的),作为客户端调用驱动
  22. /*
  23. function getDb(): \MongoDB\Driver\Manager
  24. {
  25. if ($this->db == null) {
  26. // 这里为要连接的 mongodb 的服务端地址【前提是必须先有服务端,且安装 php-mongodb 扩展才可使用】
  27. $mongoUrl = "mongodb://127.0.0.1:27017";
  28. $this->db = new \MongoDB\Driver\Manager($mongoUrl);
  29. }
  30. return $this->db;
  31. }
  32. */
  33. protected function onException(\Throwable $throwable)
  34. {
  35. Trigger::getInstance()->throwable($throwable);
  36. return null;
  37. }
  38. }

客户端调用类定义

  1. <?php
  2. namespace App\MongoDb;
  3. use EasySwoole\Component\Singleton;
  4. use EasySwoole\SyncInvoker\SyncInvoker;
  5. class MongoClient extends SyncInvoker
  6. {
  7. use Singleton;
  8. }

注册 Invoker 服务

EasySwoole 全局事件mainServerCreate 事件 中进行服务注册

  1. <?php
  2. namespace EasySwoole\EasySwoole;
  3. use EasySwoole\EasySwoole\AbstractInterface\Event;
  4. use EasySwoole\EasySwoole\Swoole\EventRegister;
  5. class EasySwooleEvent implements Event
  6. {
  7. public static function initialize()
  8. {
  9. // TODO: Implement initialize() method.
  10. date_default_timezone_set('Asia/Shanghai');
  11. }
  12. public static function mainServerCreate(EventRegister $register)
  13. {
  14. // 配置 Invoker
  15. $invokerConfig = \App\MongoDb\MongoClient::getInstance()->getConfig();
  16. $invokerConfig->setDriver(new \App\MongoDb\Driver()); // 配置 MongoDB 客户端协程调用驱动
  17. // 以下这些配置都是可选的,可以使用组件默认的配置
  18. /*
  19. $invokerConfig->setMaxPackageSize(2 * 1024 * 1024); // 设置最大允许发送数据大小,默认为 2M【注意:当使用 MongoDB 客户端查询大于 2M 的数据时,可以修改此参数】
  20. $invokerConfig->setTimeout(3.0); // 设置 MongoDB 客户端操作超时时间,默认为 3.0 秒;
  21. */
  22. // 注册 Invoker
  23. \App\MongoDb\MongoClient::getInstance()->attachServer(ServerManager::getInstance()->getSwooleServer());
  24. }
  25. }

在框架中使用 MongoDB 客户端(协程调用)

  1. <?php
  2. namespace App\HttpController;
  3. use App\MongoDb\Driver;
  4. use App\MongoDb\MongoClient;
  5. use EasySwoole\Http\AbstractInterface\Controller;
  6. use EasySwoole\Utility\Random;
  7. class Index extends Controller
  8. {
  9. public function index()
  10. {
  11. // 使用 mongodb/mongodb composer组件包【建议使用,需要先使用composer安装】
  12. $ret = MongoClient::getInstance()->invoke()->callback(function (Driver $driver) {
  13. $ret = $driver->getDb()->user->list->insertOne([
  14. 'name' => Random::character(8),
  15. 'sex' => 'man',
  16. ]);
  17. if (!$ret) {
  18. $driver->response(false);
  19. }
  20. $driver->response($ret->getInsertedId());
  21. });
  22. var_dump($ret);
  23. $ret = MongoClient::getInstance()->invoke()->callback(function (Driver $driver) {
  24. $ret = [];
  25. $collections = $driver->getDb()->user->listCollections();
  26. foreach ($collections as $collection) {
  27. $ret[] = (array)$collection;
  28. }
  29. $driver->response($ret);
  30. });
  31. var_dump($ret);
  32. /**
  33. * 输出结果:
  34. * object(MongoDB\BSON\ObjectId)#109 (1) {
  35. ["oid"]=>
  36. string(24) "600da377004c82305a02fb52"
  37. }
  38. * array(1) {
  39. [0]=>
  40. array(1) {
  41. ["MongoDB\Model\CollectionInfoinfo"]=>
  42. array(5) {
  43. ["name"]=>
  44. string(4) "list"
  45. ["type"]=>
  46. string(10) "collection"
  47. ["options"]=>
  48. array(0) {
  49. }
  50. ["info"]=>
  51. array(2) {
  52. ["readOnly"]=>
  53. bool(false)
  54. ["uuid"]=>
  55. object(MongoDB\BSON\Binary)#110 (2) {
  56. ["data"]=>
  57. string(16) "EasySwoole"
  58. ["type"]=>
  59. int(4)
  60. }
  61. }
  62. ["idIndex"]=>
  63. array(4) {
  64. ["v"]=>
  65. int(2)
  66. ["key"]=>
  67. array(1) {
  68. ["_id"]=>
  69. int(1)
  70. }
  71. ["name"]=>
  72. string(4) "_id_"
  73. ["ns"]=>
  74. string(9) "user.list"
  75. }
  76. }
  77. }
  78. }
  79. */
  80. // 使用 php-mongodb 扩展时(不使用 mongodb/mongodb composer组件包)
  81. /*
  82. // 插入数据
  83. $rets = MongoClient::getInstance()->invoke()->callback(function (Driver $driver) {
  84. $bulk = new \MongoDB\Driver\BulkWrite();
  85. $bulk->insert([
  86. 'name' => Random::character(8),
  87. 'sex' => 'man',
  88. ]);
  89. $bulk->insert(['_id' => 1, 'x' => 1]);
  90. $bulk->insert(['_id' => 2, 'x' => 2]);
  91. $bulk->update(['x' => 2], ['$set' => ['x' => 1]], ['multi' => false, 'upsert' => false]);
  92. $bulk->update(['x' => 3], ['$set' => ['x' => 3]], ['multi' => false, 'upsert' => true]);
  93. $bulk->update(['_id' => 3], ['$set' => ['x' => 3]], ['multi' => false, 'upsert' => true]);
  94. $bulk->insert(['_id' => 4, 'x' => 2]);
  95. $bulk->delete(['x' => 1], ['limit' => 1]);
  96. $manager = $driver->getDb();
  97. $writeConcern = new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY, 100);
  98. // 查到 user 库的 list 集合中
  99. $ret = $manager->executeBulkWrite('user.list', $bulk, $writeConcern);
  100. printf("Inserted %d document(s)\n", $ret->getInsertedCount()); // 插入条数
  101. printf("Matched %d document(s)\n", $ret->getMatchedCount()); // 匹配条数
  102. printf("Updated %d document(s)\n", $ret->getModifiedCount()); // 修改条数
  103. printf("Upserted %d document(s)\n", $ret->getUpsertedCount()); // 修改插入条数
  104. printf("Deleted %d document(s)\n", $ret->getDeletedCount()); // 删除条数
  105. foreach ($ret->getUpsertedIds() as $index => $id) {
  106. printf('upsertedId[%d]: ', $index);
  107. var_dump($id);
  108. }
  109. if (!$ret) {
  110. return false;
  111. }
  112. return true;
  113. });
  114. // 查询数据
  115. $rets = MongoClient::getInstance()->invoke()->callback(function (Driver $driver) {
  116. $filter = ['x' => ['$gt' => 1]];
  117. $options = [
  118. 'projection' => ['_id' => 0],
  119. 'sort' => ['x' => -1],
  120. ];
  121. // 查询数据
  122. $query = new \MongoDB\Driver\Query($filter, $options);
  123. $cursor = $driver->getDb()->executeQuery('user.list', $query);
  124. foreach ($cursor as $document) {
  125. print_r($document);
  126. }
  127. });
  128. */
  129. }
  130. }