php7 mongodb 使用(二)原生驱动 增删改查和统计

php7安装mongodb的扩展。
宝塔面板环境下php7.3默认安装了pecl扩展包, 安装的php7.4版本是默认不带pecl扩展包的。需要手动安装

php版本 < 7的时候  yum install php-pear 就可以
但是7.4 版本的不行,

$ wget http://pear.php.net/go-pear.phar
$ php go-pear.phar

安排完成后  pecl install mongodb 安装扩展
最后在php.ini 中添加  extension=mongodb.so  重启php后完成
在phpinfo中可以看到
php7 mongodb 使用(二)原生驱动 增删改查和统计

构建一个操作类
我使用的是 hyperf2.0框架 基于 Task 模式 模式构建了 操作类
 

<?php

declare(strict_types=1);

namespace App\Task;

use Hyperf\Task\Annotation\Task;
use MongoDB\Driver\BulkWrite;
use MongoDB\Driver\Manager;
use MongoDB\Driver\Query;
use MongoDB\Driver\Command;
use MongoDB\Driver\WriteConcern;
use MongoDB\BSON\UTCDateTime;

class MongoTask
{
    /**
     * @var Manager
     */
    public $manager;

    /**
     * @Task
     */
    public function insert(string $table, array $document,$type='count')
    {
        $document['time']=new UTCDateTime();
        $writeConcern = new WriteConcern(WriteConcern::MAJORITY, 1000);
        $bulk = new BulkWrite();
        $_id=$bulk->insert($document);
        $result = $this->manager()->executeBulkWrite(env('MONGODB_DB').'.'.$table, $bulk, $writeConcern);
        if($type=='count'){
            return $result->getUpsertedCount();
        }elseif ($type=='_id'){
            return $_id;
        }
    }

    /**
     * @Task
     */
    public function query(string $table='', array $filter = [], array $options = [],$type='query')
    {
        if($table){
            $table=env('MONGODB_DB').'.'.$table;
        }else{
            $table=env('MONGODB_DB');
        }
        switch ($type){
            case 'query';  /*普通结果集查询*/
                $query = new Query($filter, $options);
                $cursor = $this->manager()->executeQuery($table, $query);
                return $cursor->toArray();
            case 'command';  /*命令*/
                $command = new Command($filter);
                return $this->manager()->executeCommand($table, $command)->toArray();
            case 'update';  /*命令*/
                return $this->update($table,$filter,$options);
            default:
                return false;
        }
    }

    /**
     * @Task
     */

    public function update(string $db, array $where = [], $update = [], $upsert = false)
    {
        $writeConcern = new WriteConcern(WriteConcern::MAJORITY, 1000);
        $bulk = new BulkWrite();
        $bulk->update($where, ['$set' => $update], ['multi' => true, 'upsert' => $upsert]);

        $result = $this->manager()->executeBulkWrite($db, $bulk,$writeConcern);
        $m = $result->getModifiedCount();
        $u = $result->getUpsertedCount();
        $res = $m>$u ? $m:$u;
        if($res>0){
            return 1;
        }else{
            return 0;
        }
    }

    protected function manager()
    {
        if ($this->manager instanceof Manager) {
            return $this->manager;
        }
        $uri = 'mongodb://'.env('MONGODB_USER').':'.env('MONGODB_PASS').'@'.env('MONGODB_HOST').':'.env('MONGODB_PORT').'/'.env('MONGODB_DB');

        return $this->manager = new Manager($uri, []);
    }


}

这个类中  manager方法连接数据库
insert 方法使用  $this->manager()->executeBulkWrite() 实现插入功能;
insert 方法参数 $document 就是一个行记录的数组,$table 就是集合名称,$type 可以决定返回值 是插入的个数还是最后一个插入成功的主键 _id;

 

这个类中 query 方法我封装了 查询 原生命令 和 update 三种操作。
查询

$options=['projection' => ['_id' => 0,'user'=>1],'sort' => ['_id' => -1],'limit'=>$limit,'skip'=>$start];

参数   projection  映射  类似mysql中的 select 就是要显示哪个字段。0表示不显示 1代表显示 如果没有1 则其余的字段都会显示。

参数   sort 是排序 -1 desc  1 asc 多个字段也是可以的,limit  skip和mysql中功能一样
 

最后细说 $filter参数
$filter['_id']=new \MongoDB\BSON\ObjectId("60779eeb99cc037490518d33");
MongoDB的主键 _id是一个对象,不能直接使用字符搜索 必须需要 ObjectId 转换成对象.

$filter['user_id']=1001   这是最普通的等于搜索
$filter['time']=1618656124    //如果你存储时间是用的时间戳
$filter['time']="2021-04-17 18:42:03"    //如果你存储时间是用的字符
$filter['time']=new \MongoDB\BSON\UTCDateTime($time*1000)   
//$time 是一个时间戳
insert  方法中 获取当前时间戳对应的时间对象  $document['time']=new UTCDateTime();

$val=['$regex'=>"^a.*z$",'$options'=>'i'];  
这个是正则模糊匹配, 能支持三种参数,  ^a 以a开始,  .*  任意字符,  z$ 以z结束。
$options 必须要全小写 对应参数 i或者$i 都可以,代表大小写敏感。 这个参数很多网站上  都是 $Options=>'$i' 大小写,坑了不少人。
$filter['time']=['$gte'=>new UTCDateTime($time0*1000),'$lte'=>new UTCDateTime($time1*1000)]; 这个就相当于 mysql的 BETWEEN AND  包含边界的范围。
其中
(>) 大于 - $gt   (>=) 大于等于 - $gte
(<) 小于 - $lt    (<= ) 小于等于 - $lte
这些就是最基本的查询
$filter['type']=['$in'=>[1,2,3]]    类似mysql  in 
$filter['type']=['$nin'=>[1,2,3]]  类似mysql  not in 
$filter['type']=null        类似mysql  is_null
$filter['type']=['$ne'=>null]     类似mysql  not is_null
$filter['type']=''        空字符
$filter['type']=['$ne'=>'']     非空字符
$filter['type']=['$exists'=>true]  字段存在
$filter['type']=['$exists'=>false]  字段不存在
$filter['result']=['$type'=>"int"]  字段类型是int
$filter['result']=['$not'=>['$type'=>"string"]]  字段类型不是 string
double   array   timestamp  bool  object  undefined  null    关于mongodb支持的字段类型可以网上搜索


Command 命令

搜索一个库下集合
$cmd=['listCollections' => 1,'filter'=>['name'=>['$regex'=>'^user_log_']],'nameOnly'=>true];   
$model->query('',$cmd,[],'command');
$cmd中  'listCollections' => 1 代表要查询库下面啊的集合   filter 是过滤条件  nameOnly 是忽略账号权限。
这个不是针对某个集合的操作 是针对当前数据库的操作。query参数第一个可以留空 我封装的方法会自动识别当前db,你也可以传入某个db。

统计一个集合下的数据量  类似mysql 的 count
$cmd=["count" => $table,"query" =>$filter];
$model->query('',$cmd,[],'command');
$cmd中 count指定某个集合   query 是对集合进行过滤  $filter和搜索中的使用方法一样。

update 操作

$model->query($table,$filter,$arr,'update');
这个方法中 参数 $filter 和查询一样。
$arr=['type'=>5,'$inc'=>['num'=>1]];  type字段设置成5,num 字段自增1   如果 -1  就是自减

mongodb的基本操作就这么多了
还有聚合类操作。下一节会继续细说。











防止误删除啊a

上一篇:[PHP] php5.3之前-php5.3-php7垃圾回收机制的进化


下一篇:PHP7内存性能优化的思想精髓