mongo php类

发布时间:2020-06-11 14:54:30 作者:wjp13671142513
来源:网络 阅读:667
<?php
/**
 * mongo 类
 * User: wujp <wujp@nalashop.com>
 * Date: 13-10-12
 * Time: 下午5:48
 */

class Mongo_DB
{
    #链接
    public $conn = null;

    #mongodb
    public $db = null;

    #链接参数
    private $url = '';

    #判断db是否链接
    private $collected = null;

    #查询、更新 映射 有|
    private $four_map = array( #值是字符串,值不用处理
        '>' => '$gt',
        '>=' => '$gte',
        '<' => '$le',
        '<=' => '$lte',
        '!=' => '$ne',
        '@' => '$exists', #键是否存在
        '?' => 'perl', #正则
    );
    private $ele_map = array( #数组,值需要处理
        '~' => '$elemMatch' #内嵌文档
    );
    private $log_map = array( #值必须是数组
        '^' => '$in',
        '!^' => '$nin',
        '*' => '$all', #指定数组元素
    );
    #没有|
    private $lgi_map = array( #必须是二维数组
        '$' => '$or',
        '&' => '$and',
    );
    private $where_map = array(
        '%' => '$where', #javascript 函数
    );
    private $sort_map = array(
        'DESC' => -1,
        'ASC' => 1
    );
    #当前db下所有集合=>键数组
    public $collections = null;

    #基本配置参数
    private $config = array(
        'host' => 'localhost',
        'port' => '27017',
        'dbname' => '',
        'user' => '',
        'pass' => '',
        'logpath' => '', #日志目录
        'replicaset' => array( #集群
            'host' => array()
//            'host' => array('host:port'), #主机群
//            'options' => array('readPreference', 'readPreferenceTags', 'replicaSet','slaveok')
        ),
    );


    /**
     * 构造函数,基本参数设置
     * @param $config
     *
     */
    public function __construct($config)
    {
        if (is_array($config) && $config) {
            foreach ($this->config as $k => $v) {
                if (isset($config[$k]) && $config[$k])
                    $this->config[$k] = !is_array($config[$k]) ? trim($config[$k]) : $config[$k];
            }

            $this->connect();
        }
    }

    /**
     * 初始化mongo
     *
     */
    private function connect()
    {
        if (!extension_loaded('mongo'))
            exit('ERROR:MONGO EXTENSION NOT LOAD');

        if ($this->conn === NULL) {
            try {
                if ($this->config['replicaset']['host']) {
                    #todo 主从配置,或者副本集,读扩展,
                } else {
                    $this->url .= "mongodb://{$this->config['user']}:{$this->config['pass']}@{$this->config['host']}:
                    {$this->config['port']}/{$this->config['dbname']}";

                    $this->conn = new MongoClient($this->url);
                }

                $this->db = $this->conn->selectDB($this->config['dbname']);
                if ($this->db) {
                    $this->collected = true;
                    $this->GetAllCollection(); #获取所有集合列表
                }
            } catch (MongoConnectionException $e) {
                $this->ErrLog($e->getMessage());
                exit('MONGO CONNECT ERROR');
            }
        }
    }

    /**
     * 析构函数
     */
    public function __destruct()
    {
        $this->collected = $this->collections = $this->db = $this->conn = null;
    }

    /**
     * 获取db下所有集合名称
     *
     * @internal param $dbname
     * @return bool
     */
    private function GetAllCollection()
    {
        if (!$this->collected)
            return false;

        $colls = $this->db->listCollections();
        if ($colls) {
            foreach ($colls as $v) {
                $pos = strpos($v, $this->config['dbname']);
                if ($pos !== false)
                    $this->collections[] = substr($v, ($pos + strlen($this->config['dbname']) + 1));
            }

            return true;
        } else {
            return false;
        }
    }

    /**
     * 初始化集合对象
     * @param $collname 集合名
     * @return mixed
     */
    public function GetMonCollection($collname)
    {
        if (!$this->collected)
            return false;

        return $this->db->selectCollection($collname);
    }

    /**
     * 转换字符编码
     * @param $array
     * @return bool
     */
    private function ConvertEncode($array)
    {
        if (is_array($array)) {
            foreach ($array as &$v) {
                if (is_array($v)) {
                    $v = $this->ConvertEncode($v);
                    if (!$v)
                        return false;
                } else {
                    $code = mb_detect_encoding($v, array('UTF-8', 'ASCII', 'GB2312', 'GBK', 'CP936'), true);
                    if ($code !== 'UTF-8')
                        $v = mb_convert_encoding($v, 'UTF-8', $code);
                }
            }

            return $array;
        }
        return false;
    }

    /**
     * 获取where参数
     * @param $where
     * @param bool $type
     * @return string
     *
     */
    private function GetWhere($where, $type = false)
    {
        $wheres = array();
        $maps = array('four_map', 'log_map', 'ele_map');
        $maps_np = array_merge($this->lgi_map, $this->where_map);

        if (is_array($where) && $where) { #过滤查询条件
            foreach ($where as $field => $val) {
                $pos = strpos($field, '|');

                if ($pos !== false) { #四则、正则、函数、数组、in、多重条件内嵌文档
                    $tep = substr($field, 0, $pos);
                    $key = substr($field, ($pos + 1));

                    if ($key !== false) {
                        foreach ($maps as $v) {
                            $arr = $this->$v;
                            if (in_array($tep, array_keys($arr))) {
                                if ($v == 'ele_map' && is_array($val))
                                    $val = $this->GetWhere($val, true);

                                if ($tep == '?') { #正则
                                    $val = new MongoRegex($val);
                                    $wheres[$key] = $val;
                                } else {
                                    $wheres[$key][$arr[$tep]] = $val;
                                }
                            }
                        }
                    }
                } elseif (in_array($field, array_keys($maps_np))) {
                    if (in_array($field, array_keys($this->lgi_map)) && is_array($val)) { #逻辑
                        foreach ($val as $v) {
                            $val = $this->GetWhere($v, true);
                            $wheres[$maps_np[$field]][] = $val;
                        }

                    } else {
                        $wheres[$maps_np[$field]] = $val;
                    }
                } else { #普通查询、单一条件内嵌文档
                    if (strpos($field, "[") !== false)
                        $field = str_replace("[", ".", $field);

                    if (is_array($val) && $type) {
                        $arr = $this->GetWhere($val);
                        foreach ($arr as $k => $v) {
                            $wheres[$k][] = $v;
                        }
                    } elseif (is_null($val)) {
                        $wheres[$field] = array('$in' => array(null), '$exists' => 1);
                    } else {
                        $wheres[$field] = $val; #支持 array('age'=>array('>'=>'18','<='=>'20'))
                    }
                }
            }
        }

        return $wheres;
    }

    /**
     * 插入一行
     * @param $collect
     * @param $value
     * @return bool
     */
    public function InsOne($collect, $value)
    {
        if (!$this->collected || !is_array($value))
            return false;

        $id = array_search('id', array_keys($value)); #处理有id字段的情况
        if ($id !== false && array_search('_id', array_keys($value)) === false) {
            $value['_id'] = $value['id'];
            unset($value['id']);
        }

        $value = $this->ConvertEncode($value);
        if (!$value)
            return false;

        try {
            $result = $this->GetMonCollection($collect)->insert($value);
            $result = $result['err'] ? false : true;
        } catch (MongoException $e) {
            $this->ErrLog($e->getMessage());
            return false;
        }

        return $result;
    }

    /**
     * 插入多行
     * @param $collect 集合
     * @param $fields
     * @param $values 键值对:array(0=>array(''=>''))
     * @param bool $continueOnError 是否忽略插入错误,默认忽略
     * @return bool
     */
    public function InsMulit($collect, $fields, $values, $continueOnError = false)
    {
        if (!is_array($fields) || !is_array($values) || !$this->collected)
            return false;

        $id = array_search('id', $fields); #处理有id字段的情况
        if ($id !== false && array_search('_id', $fields) === false)
            $fields[$id] = '_id';

        $data = array();
        $values = $this->ConvertEncode($values);
        if ($values) {
            foreach ($values as $v) {
                if (is_array($v)) {
                    $v = array_combine($fields, $v);
                    if ($v)
                        $data[] = $v;
                }
            }
        }
        if (!$data)
            return false;

        $option['continueOnError'] = $continueOnError ? true : false;
        try {
            $result = $this->GetMonCollection($collect)->batchinsert($data, $option);
            $result = $result['err'] ? false : true;
        } catch (MongoException $e) {
            $this->ErrLog($e->getMessage());
            return false;
        }

        return $result;
    }

    /**
     * 查询一个
     * @param $collect
     * @param array $where
     * @param $field string
     * @return bool
     */
    function FindOne($collect, $where = array(), $field)
    {
        if (!$this->collected)
            return false;

        $wheres = $this->GetWhere($where);
        if ($where && !$wheres)
            return false;

        if (is_string($field) && trim($field))
            $field = trim($field);
        else
            return false;

        $result = $this->GetMonCollection($collect)->findOne($wheres, array($field));

        if ($result) {
            $arr = get_object_vars($result['_id']);
            $result['_id'] = $arr['$id'];

            return $result[$field];
        }

        return false;
    }

    /**
     * 查询一条
     * @param $collect
     * @param array|string $where
     * @param array $fields
     * @param string $type
     * @return array|bool
     */
    function FindRow($collect, $where = array(), $fields = array(), $type = 'assoc')
    {
        if (!$this->collected)
            return false;

        $wheres = $this->GetWhere($where);
        if ($where && !$wheres)
            return false;

        if ($fields && is_array($fields)) { #过滤fields
            $val = '';
            for ($i = 0; $i < count($fields); $i++) {
                $val[] = 1;
            }
            $fields = array_combine($fields, $val);
        } else {
            $fields = array();
        }

        $result = $this->GetMonCollection($collect)->findOne($wheres, $fields);

        if ($result) {
            if (in_array('_id', $fields)) {
                $arr = get_object_vars($result['_id']);
                $result['_id'] = $arr['$id'];
            } else {
                unset($result['_id']);
            }

            if (strtolower($type) == 'array')
                $result = array_values($result);

            return $result;
        }

        return false;
    }

    /**
     * 复合查询  todo 查询高级选项扩展 snapshot maxscan  min max hint explain
     * <-----------------------
     * $gt:>|$gte:>=|$le:<|$lte:<=|$ne:!=
     * array('x'=>array('$gt'=>'20'))
     *
     * $or:$|$end:&
     * array('x'=>array('$in'=>array('1','2')))
     *
     * $where:%
     * array('x'=>array('$where'=>function))
     *
     * 正则表达式:
     * ?
     *
     * 数组:
     * $all:*
     *
     * 内嵌文档:
     * 单个条件:username.user   username[user
     * 多个条件:$elemMatch
     *
     * 逻辑操作符:
     * not:!
     * or:$
     * end:&
     * sort
     * array('x'=>0)
     *
     * limit|skip
     * $where = array('&|'=>array('she_hash' => '48b6c531ef2469469ede4ac21eebcf51', 'type' => 'doing'));
     * $field = array('time', '_id' => 0);
     * $res = $mongo->FindMix('sapilog', $where, $field,'1,2',array('time'=>'desc'));
     * ------------------------->
     * @param $collect |string
     * @param string $where |array array('>|x'=>'10','<=|x'=>'20','^|x'=>array(),'%|x'=>'fun')
     * @param array|string $fields |array|string 返回字段 默认为全部 字符串返回一个字段,键为数字则为返回该字段,键为字段,值为-1为不返回该字段
     * @param string $limit |string  skip,limit  0,10 如果没有 默认 skip为0 limit为当前变量
     * @param string $sort |array array('x'=>'desc|asc') desc=>-1 asc=>
     * @param string $type  | string 返回类型 默认为关联数组 assoc|array
     * @return bool
     */
    public function FindMix($collect, $where = '', $fields = array(), $limit = '', $sort = '', $type = 'assoc')
    {
        if (!$this->collected)
            return false;

        $wheres = $this->GetWhere($where);
        if ($where && !$wheres)
            return false;

        if ($fields && is_array($fields)) { #过滤fields
            $val = '';
            for ($i = 0; $i < count($fields); $i++) {
                $val[] = 1;
            }
            $fields = array_combine($fields, $val);
        } else {
            $fields = array();
        }

        $limits = '';
        $skip = '';
        if (is_string($limit)) { #过滤limit
            $limit = explode(",", trim($limit));
            if ($limit && is_numeric(implode('', $limit))) {
                if (count($limit) == 1) {
                    $limits = $limit[0];
                } else {
                    $skip = $limit[0];
                    $limits = $limit[1];
                }
            }
        } elseif (is_numeric($limit)) {
            $limits = trim($limit);
        }

        $sorts = '';
        if (is_array($sort) && $sort) { #过滤sort
            foreach ($sort as $k => $v) {
                $k = trim($k);
                $v = strtoupper(trim($v));
                if (in_array($v, array_keys($this->sort_map))) {
                    $sorts[$k] = $this->sort_map[$v];
                }
            }
        }

        $result = $this->GetMonCollection($collect)->find($wheres, $fields);
        if ($skip)
            $result = $result->skip($skip);
        if ($limits)
            $result = $result->limit($limits);
        if ($sorts)
            $result = $result->sort($sorts);

        if ($result) {
            $return = array();
            foreach ($result as $v) {
                $return[] = $v;
            }
            foreach ($return as &$v) {
                if (in_array('_id', $fields)) {
                    $arr = get_object_vars($v['_id']);
                    $v['_id'] = $arr['$id'];
                } else {
                    unset($v['_id']);
                }

                if (strtolower($type) == 'array')
                    $v = array_values($v);
            }

            return $return;
        }

        return false;
    }

    /**
     * 修改记录
     * $inc、$set、$unset 修改普通文档,如果有就修改,没有就条件加值创建,前者只支持数字类型,使用后者,$unset删除元素
     * $push、$addToSet 添加数组元素,前者不去重,使用后者
     * $pop、$pull 删除数组元素,前者删除前后,后者删除指定元素,使用后者
     *
     * @param $collect
     * @param $where
     * @param $newdata |array
     * @param string $type   操作类型 upd修改 unset删除指定元素 arr修改数组元素 pull删除数组元素
     * @param bool $upsert 是否创建
     * @param int $return |1:返回bool,2:返回影响行数
     * @return bool
     */
    public function UpdMix($collect, $where, $newdata, $type = 'upd', $upsert = false, $return = 1)
    {
        if (!$this->collected || !is_array($newdata))
            return false;

        $wheres = $this->GetWhere($where);
        if (!$wheres) {
            $this->ErrLog('where is error');
            return false;
        }

        $newdata = $this->ConvertEncode($newdata);

        $type = strtolower(trim($type));
        $types = array('upd' => '$set', 'unset' => '$unset', 'arr' => '$addToSet', 'pull' => '$pull');
        if (isset($types[$type])) {
            $option = array();
            if ($type == 'upd')
                $option = array('multiple' => true);
            if (in_array($type, array('upd', 'arr')) && $upsert)
                $option['upsert'] = true;

            $newdata = array($types[$type] => $newdata);
        } else {
            return false;
        }

        try {
            $result = $this->GetMonCollection($collect)->update($wheres, $newdata, $option);
            $result = $return == 1 ? ($result['err'] ? false : true) : $result['n'];
        } catch (MongoConnectionException $e) {
            $this->ErrLog($e->getMessage());
            return false;
        }

        return $result;
    }

    #todo EXPLAIN 函数

    /**
     * 对集合执行命令
     * @param $data
     * @return bool
     */
    public function RunCommand($data)
    {
        if (is_array($data) && $data && $this->collected) {
            $result = $this->db->command($data);

            if (isset($result['values']))
                return $result['values'];
            else
                $this->ErrLog("command error,info:" . $result['errmsg'] . ",bad_cmd:" . json_encode($result['bad cmd']));

        }
        return false;
    }

    /**
     * todo 聚合
     *
     */
    public function Group()
    {

    }

    public function Count($collect, $where = array())
    {
        if (!$this->collected)
            return false;

        $wheres = $this->GetWhere($where);
        if ($where && !$wheres)
            return false;

        return $this->GetMonCollection($collect)->count($wheres);
    }

    /**
     * 返回指定键的唯一值列表
     * @param $collect
     * @param $key
     * @param array $where 额外查询条件
     * @return bool
     */
    public function Distinct($collect, $key, $where = array())
    {
        if (!$this->collected)
            return false;

        $wheres = $this->GetWhere($where);
        if ($where && !$wheres)
            return false;

        try {
            $result = $this->GetMonCollection($collect)->distinct($key, $wheres);
        } catch (MongoException $e) {
            $this->ErrLog($e->getMessage());
            return false;
        }

        return $result;
    }

    /**
     * 删除集合中的记录
     * @param $collect
     * @param $where
     * @param int $return 1:返回bool,2:返回影响行数
     * @return bool
     */
    public function RemoveColl($collect, $where, $return = 1)
    {
        if (!$this->collected)
            return false;

        $wheres = $this->GetWhere($where);
        if (!$wheres) {
            $this->ErrLog('where is error');
            return false;
        }

        try {
            $result = $this->GetMonCollection($collect)->remove($wheres);
            $result = $return == 1 ? ($result['err'] ? false : true) : $result['n'];
        } catch (MongoConnectionException $e) {
            $this->ErrLog($e->getMessage());
            return false;
        }

        return $result;
    }

    /**
     * mongo 错误日志函数
     *
     * @param $msg
     * @param int $lever
     *
     */
    private function ErrLog($msg, $lever = 2)
    {
        global $__CFG;

        $trace = debug_backtrace();
        $error_log = '';
        $date = date("Ymd", time());

        $line = isset($trace[$lever]['line']) ? trim($trace[$lever]['line']) : '';
        $file = isset($trace[$lever]['file']) ? trim($trace[$lever]['file']) : '';

        $object = isset($trace[$lever]['object']) ? get_class($trace[$lever]['object']) : '';
        $args = isset($trace[$lever]['args']) ? json_encode($trace[$lever]['args']) : '';

        $error_log .= "line {$line} " . ($object ? 'of ' . $object : '') . "(in {$file})\n";
        $error_log .= $args ? "args:{$args}\n" : '';
        $error_log .= "msg:{$msg}";


        if (isset($__CFG['com']['id']) && $__CFG['com']['id']) {
            $com_id = $__CFG['com']['id'];
        } else {
            $com_id = 'common';
        }

        $log_dir = $this->config['logpath'] ? $this->config['logpath'] : __ROOT__ . "data/nginx_error_log/{$com_id}/{$date}/mongo.nginx_error_log";
        error_log("Date:" . date("Y-m-d H:i:s", $date) . "\nstamp:{$date}\ntrace:{$error_log}\n\n", 3, $log_dir);

        if (isset($__CFG['currUser']) && $__CFG['currUser'] == 'root' && isset($__CFG['daemon']['user'])) {
            $paths = explode("nginx_error_log/", $log_dir);
            $pathc = explode("/", $paths[1]);
            $pathd = $paths[0] . "nginx_error_log";
            foreach ($pathc as $v) {
                $pathd .= "/" . $v;
                chgrp($pathd, $__CFG['daemon']['user']);
                chown($pathd, $__CFG['daemon']['user']);
            }
        }
    }
}


附件:http://down.51cto.com/data/2364629
推荐阅读:
  1. mongo性能测试
  2. lnmp 用mongo

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

php class mongo

上一篇:php如何将数字转为字符串

下一篇:JavaScript中“==”和“===”的区别是什么?

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》