|
@@ -0,0 +1,364 @@
|
|
|
+<?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;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 返回一个新的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) {
|
|
|
+ try {
|
|
|
+ $this->mc = new \MongoDB\Driver\Manager($connStr);
|
|
|
+ return $this->mc;
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ Clog::err($e->getMessage());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询
|
|
|
+ * @author gwang<wanggangzero@qq.com>
|
|
|
+ * @param string $collection 集合
|
|
|
+ * @param array $filter
|
|
|
+ * @param array $options
|
|
|
+ * @return \MongoDB\Driver\Cursor|false
|
|
|
+ */
|
|
|
+ public function find($collection, $filter = [], $options = []) {
|
|
|
+ if (empty($this->mc)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ $query = new \MongoDB\Driver\Query($filter, $options);
|
|
|
+ $cursor = $this->mc->executeQuery($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($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];
|
|
|
+ $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($collection, $bulk, $writeConcern);
|
|
|
+ return $result->getDeletedCount();
|
|
|
+ } 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>
|
|
|
+}
|