123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- <?php
- namespace loyalsoft;
- /*
- * File:MongoUtil.php
- * Function: MongoDB operation helper.
- * Author: gwang(wanggangzero@qq.com)
- * Version:
- * 1.0.0 Creat file. --gwang 2022.2.14
- */
- /**
- * MongoDB辅助类
- * Author: gwang(wanggangzero@qq.com)
- */
- class MongoUtil {
- /**
- * 负责与MongoDB连接, 管理
- * @var \MongoDB\Driver\Manager
- */
- private $mc;
- private $dbPrefix = "";
- /**
- * 返回一个新的option构造器,请使用链式写法追加所有option, 最后用GetOption()获取最终的option数组
- * @author gwang <wanggangzero@qq.com>
- * @return \loyalsoft\MongoQueryOptionBuilder
- */
- public static function QueryOptionBuilder() {
- return new MongoQueryOptionBuilder();
- }
- /**
- *
- * @param type $connStr
- * @return \MongoDB\Driver\Manager|false
- */
- public function conn($connStr, $dbPrefix = "") {
- try {
- $this->mc = new \MongoDB\Driver\Manager($connStr);
- $this->dbPrefix = $dbPrefix;
- return $this->mc;
- } catch (\Exception $e) {
- Clog::err($e->getMessage());
- return false;
- }
- }
- /**
- * 查询,返回的是光标,也可以用toArray()转换为数组使用
- * @author gwang<wanggangzero@qq.com>
- * @param string $collection 集合
- * @param array $filter 同过滤器语法
- * @param array $options 请利用QueryOptionBuilder()来辅助定制选项
- * @return \MongoDB\Driver\Cursor|false 访问光标或者false, 可以用foreach来访问Cursor
- */
- public function find($collection, $filter = [], $options = []) {
- if (empty($this->mc)) {
- return false;
- }
- try {
- $query = new \MongoDB\Driver\Query($filter, $options);
- $cursor = $this->mc->executeQuery($this->dbPrefix . '.' . $collection, $query);
- return $cursor;
- } catch (\Exception $ex) {
- CLog::err($ex->getMessage());
- return false;
- }
- }
- /**
- * 插入1条数据
- * @param string $collection 表名(db.collection)
- * @param array $addArr 待插入的数据,要求是数组
- * @return boolean
- */
- public function insert($collection, $addArr) {
- if (empty($addArr) || !is_array($addArr)) {
- return false;
- }
- if (empty($this->mc)) {
- return false;
- }
- try {
- $bulk = new \MongoDB\Driver\BulkWrite();
- $bulk->insert($addArr);
- $writeConcern = new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY, 6000);
- $result = $this->mc->executeBulkWrite($this->dbPrefix . '.' . $collection, $bulk, $writeConcern);
- if ($result->getInsertedCount()) {
- return true;
- }
- } catch (\Exception $e) {
- CLog::err($e->getMessage()); # 记录错误日志
- }
- return false;
- }
- /**
- * 删除
- * @param string $collection 表名
- * @param array $whereArr 筛选条件
- * @param bool $limit 是否仅删除第一条(默认false,删除所有匹配条目)
- * @return boolean
- */
- public function delete($collection, $whereArr, $limit = false) {
- if (empty($whereArr)) {
- return false;
- }
- $options = ['limit' => $limit ? 1 : 0];
- $conn = $this->mc;
- if (empty($conn)) {
- return false;
- }
- try {
- $bulk = new \MongoDB\Driver\BulkWrite();
- $bulk->delete($whereArr, $options);
- $writeConcern = new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY, 30000);
- $result = $conn->executeBulkWrite($this->dbPrefix . '.' . $collection, $bulk, $writeConcern);
- return $result->getDeletedCount();
- } catch (\Exception $e) {
- CLog::err($e->getMessage()); # 记录错误日志
- }
- return false;
- }
- /**
- * 更新
- * @param string $collection
- * @param array $whereArr 条件
- * @param array $newPropertiesArr 可以是一个新文档, 也可以是一个opration数组(eg. $set表达式), 还可以是一组update 管道(批量参考https://docs.mongodb.com/manual/reference/command/update/#update-with-an-aggregation-pipeline)
- * @param bool $upsert 当符合条件的文档不存在时是否作为一条新的文档插入(当新数据为文档时生效,operation不可以)
- * @param bool $multi 是否一次更新多个文档的值(当新数据为operation表达式时可以,否则不可以) 默认false
- * @return boolean
- */
- public function update($collection, $whereArr, $newPropertiesArr, $upsert = true, $multi = false) {
- if (empty($whereArr) || empty($newPropertiesArr)) {
- return false;
- }
- $options = ['multi' => $multi, 'upsert' => $upsert];
- $conn = $this->mc;
- if (empty($conn)) {
- return false;
- }
- try {
- $bulk = new \MongoDB\Driver\BulkWrite();
- $bulk->update($whereArr, $newPropertiesArr, $options);
- $writeConcern = new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY, 30000);
- $result = $conn->executeBulkWrite($this->dbPrefix . '.' . $collection, $bulk, $writeConcern);
- return $result->getUpsertedCount() + $result->getModifiedCount();
- } catch (\Exception $e) {
- CLog::err($e->getMessage()); # 记录错误日志
- }
- return false;
- }
- }
- /**
- * 查询选项构造器
- * @author gwang <wanggangzero@qq.com>
- */
- class MongoQueryOptionBuilder {
- /**
- * 内部对象
- */
- private $option = array();
- /**
- * 返回最终的 options
- * @return array
- */
- public function GetOption() {
- return $this->option;
- }
- /**
- * 参照MySQL的 explain
- * @param bool $yes
- * @return MongoQueryOptionBuilder
- */
- public function explain($yes = true) {
- $this->option[__FUNCTION__] = $yes;
- return $this;
- }
- /**
- * 限定返回值数量(0=无限制)
- * @param int $limit 默认 0
- * @return MongoQueryOptionBuilder
- */
- public function limit($limit = 0) {
- $this->option[__FUNCTION__] = $limit;
- return $this;
- }
- /**
- * 限定返回值跳过前n个文档(索引从0开始)
- * @param int $n 默认值0
- * @return MongoQueryOptionBuilder
- */
- public function skip($n = 0) {
- $this->option[__FUNCTION__] = $n;
- return $this;
- }
- /**
- * project
- * @param array $arr 假如MQL中为{$project:{key:1,name:"$value.baseInfo.name"}}
- * 则此处['key'=>1,'name'=>'$value.baseInfo.name'] 注意如果包含$符使用单引号
- * @return MongoQueryOptionBuilder
- */
- public function projection($arr = array()) {
- $this->option[__FUNCTION__] = $arr;
- return $this;
- }
- /**
- * 必须与 tailable awaitData 结合使用.
- * 设定正整数值可以让服务器阻塞对应的毫秒数(没有数据的前提下,有数据自然直接返回)
- * @param int $n
- * @return MongoQueryOptionBuilder
- */
- public function maxAwaitTimeMS($n = 0) {
- $this->option[__FUNCTION__] = $n;
- return $this;
- }
- /**
- * 只返回索引
- * @param bool $yes 默认值false, 当设为true时,你应该了解会返回什么.
- * @return $this
- */
- public function returnKey($yes = false) {
- $this->option[__FUNCTION__] = $yes;
- return $this;
- }
- /**
- * The sort specification for the ordering of the results.
- * Falls back to the deprecated modifier if not specified. "$orderby"
- * @param array $arr 假如MQL中为{$sort:{"value.baseInfo.level":-1}则对应["value.baseInfo.level"=>-1]
- * @return MongoQueryOptionBuilder
- */
- public function sort($arr = array()) {
- $this->option[__FUNCTION__] = $arr;
- return $this;
- }
- // <editor-fold defaultstate="collapsed" desc="不常用或已经废弃的">
- /**
- * 不了解, 先不要使用
- * @deprecated since version 0
- * @param type $yes
- * @return $this
- */
- public function allowDiskUse($yes = true) {
- $this->option[__FUNCTION__] = $yes;
- return $this;
- }
- /**
- * 不了解, 先不要使用
- * @deprecated since version 0
- * @param type $yes
- * @return $this
- */
- public function allowPartialResults($yes = true) {
- $this->option[__FUNCTION__] = $yes;
- return $this;
- }
- /**
- * 不了解, 先不要使用
- * @deprecated since version 0
- * @param type $yes
- * @return $this
- */
- public function awaitData($yes = true) {
- $this->option[__FUNCTION__] = $yes;
- return $this;
- }
- /**
- * 返回值第一批的文档数,默认值为101,设置为0表示将建立光标,但不返回任何文档
- * @deprecated since version 0 不懂,先不要用
- * @param type $size
- * @return MongoQueryOptionBuilder
- */
- public function batchSize($size = 101) {
- $this->option[__FUNCTION__] = $size;
- return $this;
- }
- /**
- * 语言设置
- * @deprecated since version 0 这个太复杂还没研究,先不要用
- * @param array|object $collation
- * @return MongoQueryOptionBuilder
- */
- public function collation($collation = array()) {
- $this->option[__FUNCTION__] = $collation;
- return $this;
- }
- /**
- * 注释
- * @param type $msg
- * @return MongoQueryOptionBuilder
- */
- public function comment($msg = "默认注释") {
- $this->option[__FUNCTION__] = $msg;
- return $this;
- }
- /**
- * 尽最大努力下载数据,(从3.2+已经不再支持)
- * @deprecated since version mongodb 3.2+
- * @param type $yes
- * @return MongoQueryOptionBuilder
- */
- public function exhaust($yes = true) {
- $this->option[__FUNCTION__] = $yes;
- return $this;
- }
- /**
- * 不懂, 先不要用
- * @deprecated since version 0 在某个index的上限(不包含上限值)
- * @param array $arr
- * @return MongoQueryOptionBuilder
- */
- public function max($arr = array()) {
- $this->option[__FUNCTION__] = $arr;
- return $this;
- }
- /**
- * 不懂,先不要用
- * @deprecated since version 0 在某个index的下限(包含下限值)
- * @param array $arr
- * @return MongoQueryOptionBuilder
- */
- public function min($arr = array()) {
- $this->option[__FUNCTION__] = $arr;
- return $this;
- }
- /**
- * @deprecated since version 0 已经废弃
- * @param int $i
- * @throws \Exception
- */
- public function maxScan($i = 0) {
- throw new \Exception("Deprecated!");
- }
- /**
- * Determines whether to close the cursor after the first batch. Defaults to false.
- * @param bool $yes
- * @deprecated since version 0 不放心, 先不要用
- * @return MongoQueryOptionBuilder
- */
- public function singleBatch($yes = false) {
- $this->option[__FUNCTION__] = $yes;
- return $this;
- }
- /**
- * Determines whether to return the record identifier for each document.
- * If true, adds a top-level field to the returned documents. "$recordId"
- * @deprecated since version 0 这个感觉没啥用,也没测试过,先不要用
- * @param bool $yes
- * @return $this
- */
- public function showRecordId($yes = false) {
- $this->option[__FUNCTION__] = $yes;
- return $this;
- }
- /**
- * Returns a tailable cursor for a capped collection.
- * @deprecated since version 0 不懂,先不要用
- * @param type $yes
- * @return MongoQueryOptionBuilder
- */
- public function tailable($yes = false) {
- $this->option[__FUNCTION__] = $yes;
- return $this;
- }
- // </editor-fold>
- }
|