1. 什么是MongoDB
一套高性能、易开发的文档型数据库。他使用键值对形式存放数据,能够存放包括字符串、数组、数据序列、图片、视频等在内的大多数数据文档。
2. MongoDB的使用原理
它的特点是高性能、易部署、易使用,存储数据非常方便。主要功能特性有:
所谓“面向集合”(Collection-Oriented),意思是数据被分组存储在数据集中,被称为一个集合(Collection)。每个集合在数据库中都有一个唯一的标识名,并且可以包含无限数目的文档。集合的概念类似关系型数据库(RDBMS)里的表(table),不同的是它不需要定义任何模式(schema)。Nytro MegaRAID技术中的闪存高速缓存算法,能够快速识别数据库内大数据集中的热数据,提供一致的性能改进。
模式自由(schema-free),意味着对于存储在mongodb数据库中的文件,我们不需要知道它的任何结构定义。如果需要的话,你完全可以把不同结构的文件存储在同一个数据库里。
存储在集合中的文档,被存储为键-值对的形式。键用于唯一标识一个文档,为字符串类型,而值则可以是各种复杂的文件类型。我们称这种存储形式为BSON(Binary Serialized Document Format)。
3. 应用场景
在项目实践过程中,对于MongoDB可以以集群的方式部署,以支持海量的数据。下面列一些适用和非适用的场景。
适用场景
网站数据:Mongo 非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
缓存:由于性能很高,Mongo 也适合作为信息基础设施的缓存层。在系统重启之后,由Mongo 搭建的持久化缓存层可以避免下层的数据源过载。
大尺寸、低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储。
高伸缩性的场景:Mongo 非常适合由数十或数百台服务器组成的数据库,Mongo 的路线图中已经包含对MapReduce 引擎的内置支持。
用于对象及JSON 数据的存储:Mongo 的BSON 数据格式非常适合文档化格式的存储及查询。
不适用场景
高度事务性的系统:例如,银行或会计系统。传统的关系型数据库目前还是更适用于需要大量原子性复杂事务的应用程序。
4. MongoDB操作类封装
正是因为要封装这么一个类,才整理的这篇内容。背景是TP5框架,基于PHP7+,需要先安装mongodb扩展,没有可以这里下载https://pecl.php.net/package/mongodb
工具类代码:
<?php
namespace mongodb;
use think\Env;
use MongoDB\Driver\Manager;
use MongoDB\Driver\BulkWrite;
use MongoDB\BSON\ObjectID;
use MongoDB\Driver\WriteConcern;
use MongoDB\Driver\Query;
use MongoDB\Driver\Command;
/**
* Tablestore增删改查操作类
*/
class MongodbUtil
{
protected $dbname;
protected $collection;
protected $manager;
public function __construct()
{
$this->manager = new Manager(Env::get('mongodb.uri'));
$this->dbname = Env::get('mongodb.dbname');
$this->collection = Env::get('mongodb.collection');
}
/**
* 插入数据
* @param array $data 数据数组
* @param string $dbname 数据库名
* @param string $collection 集合名称
* @return [type] 唯一id
*/
public function insert($data=[],$dbname='',$collection=''){
if(!$dbname) $dbname = $this->dbname;
if(!$collection) $collection = $this->collection;
try {
$bulk = new BulkWrite;
$document = array_merge(['_id' => new ObjectID],$data);
$_id= $bulk->insert($document);
$writeConcern = new WriteConcern(WriteConcern::MAJORITY, 1000);
$result = $this->manager->executeBulkWrite($dbname.'.'.$collection, $bulk, $writeConcern);
return $this->jsonReturn(200,'插入成功',get_object_vars($_id)['oid']);
} catch (\Exception $e) {
return $this->jsonReturn($e->getCode(),$e->getMessage());
}
}
/**
* 删除
* @param array $where 条件
* @param integer $limit 限制 0-删除所有 1-删除第一条匹配数据
* @param string $dbname 数据库名
* @param string $collection 集合名称
* @return [type] json
*/
public function delete($where=[],$limit=1,$dbname='',$collection=''){
if(!$dbname) $dbname = $this->dbname;
if(!$collection) $collection = $this->collection;
try {
$bulk = new BulkWrite;
$bulk->delete($where, ['limit' => $limit]);
$writeConcern = new WriteConcern(WriteConcern::MAJORITY, 1000);
$result = $this->manager->executeBulkWrite($dbname.'.'.$collection, $bulk, $writeConcern);
return $this->jsonReturn(200,'删除成功');
} catch (\Exception $e) {
return $this->jsonReturn($e->getCode(),$e->getMessage());
}
}
/**
* 更新
* @param array $where 条件
* @param array $data 数据
* @param boolean $multi 是否批量
* @param string $dbname 库名
* @param string $collection 集合
* @return [type] json
*/
public function update($where=[],$data=[],$multi=false,$dbname='',$collection=''){
if(!$dbname) $dbname = $this->dbname;
if(!$collection) $collection = $this->collection;
try {
$bulk = new BulkWrite;
$bulk->update(
$where,
['$set' => $data],
['multi' => $multi, 'upsert' => false]
);
$writeConcern = new WriteConcern(WriteConcern::MAJORITY, 1000);
$result = $this->manager->executeBulkWrite($dbname.'.'.$collection, $bulk, $writeConcern);
return $this->jsonReturn(200,'更新成功');
} catch (\Exception $e) {
return $this->jsonReturn($e->getCode(),$e->getMessage());
}
}
/**
* 查询
* @param array $where 条件
* @param integer $skip 偏移量
* @param integer $limit 限制
* @param array $sort 排序
* @param string $dbname 库名
* @param string $collection 集合
* @return [type] json
*/
public function select($where=[],$skip=0,$limit=10,$sort=[],$dbname='',$collection=''){
if(!$dbname) $dbname = $this->dbname;
if(!$collection) $collection = $this->collection;
try {
$options = [
'skip' => $skip,
'sort' => $sort,
];
if($limit > 0){
$options['limit'] = $limit;
//查询记录总的数量
$commands = [
'count' => $collection,
'query' => $where
];
$command = new Command($commands);
$cursor = $this->manager->executeCommand($dbname, $command);
$info = $cursor->toArray();
$total = $info[0]->n;
$page = ($skip+$limit)/$limit;
$page_count = ceil($total/$limit);
}
$query = new Query($where, $options);
$cursor = $this->manager->executeQuery($dbname.'.'.$collection, $query);
if($limit > 0){
$pageInfo = [
'page'=>$page,//当前页
'page_size'=>$limit,//每页数量
'page_count'=>$page_count,//分页总数
'total'=>$total,//数据总数
];
}else{
$pageInfo = [];
}
$list = [];
foreach ($cursor as $document) {
$list[] = get_object_vars($document);
}
return $this->jsonReturn(200,'获取成功',['list'=>$list,'pageInfo'=>$pageInfo]);
} catch (\Exception $e) {
return $this->jsonReturn($e->getCode(),$e->getMessage());
}
}
/**
* 查询总数量
* @param array $where 条件
* @param string $dbname 库名
* @param string $collection 集合
* @return [type] json
*/
public function count($where=[],$dbname='',$collection=''){
if(!$dbname) $dbname = $this->dbname;
if(!$collection) $collection = $this->collection;
try {
//查询记录总的数量
$commands = [
'count' => $collection,
'query' => $where
];
$command = new Command($commands);
$cursor = $this->manager->executeCommand($dbname, $command);
$info = $cursor->toArray();
$count = $info[0]->n;
return $this->jsonReturn(200,'获取成功',$count);
} catch (\Exception $e) {
return $this->jsonReturn($e->getCode(),$e->getMessage());
}
}
/**
* 取一条记录
* @param array $where 条件
* @param array $sort 排序
* @param string $dbname 库名
* @param string $collection 集合
* @return [type] json
*/
public function find($where=[],$sort=[],$dbname='',$collection=''){
if(!$dbname) $dbname = $this->dbname;
if(!$collection) $collection = $this->collection;
try {
$options = [
'limit' => 1,
'sort' => $sort,
];
$query = new Query($where, $options);
$cursor = $this->manager->executeQuery($dbname.'.'.$collection, $query);
$res = [];
foreach ($cursor as $document) {
$res = get_object_vars($document);
}
return $this->jsonReturn(200,'获取成功',$res);
} catch (\Exception $e) {
return $this->jsonReturn($e->getCode(),$e->getMessage());
}
}
/**
* json格式返回
* @param int $code 状态码 200-成功 其他-失败
* @param string $msg 状态描述or错误信息
* @param array $data 数据数组
* @return string json
*/
private function jsonReturn($code=0,$msg='',$data=[]){
return ["code"=>$code,"msg"=>$msg,"data"=>$data];
}
}
配置我设置在.env中,admin:admin是账号密码,未设置可去掉。uri可以是mongodb://127.0.0.1:27017
[mongodb]
uri = mongodb://admin:admin@127.0.0.1:27017/test
dbname = test
collection = test
一些操作例子:
<?php
namespace app\api\controller;
use app\common\controller\Api;
use mongodb\MongodbUtil;
/**
* Mongodb接口
*/
class Mongodb extends Api
{
protected $noNeedLogin = ['*'];
// 无需鉴权的接口,*表示全部
protected $noNeedRight = ['*'];
protected $mongodbUtil;
public function _initialize()
{
$this->mongodbUtil = new MongodbUtil();
parent::_initialize();
}
/**
* 新增
*/
public function insert(){
$dbname = '';//为空则取默认库
$collection = '';//为空则取默认集合
$data = ['name'=>'张三1','age'=>25];
$res = $this->mongodbUtil->insert($data,$dbname,$collection);
var_dump($res);
exit();
}
/**
* 删除
*/
public function delete(){
$where = ['name'=>'张三1'];//条件
$limit = 1;//0-删除所有 1-删除第一条匹配数据
$dbname = '';//为空则取默认库
$collection = '';//为空则取默认集合
$res = $this->mongodbUtil->delete($where,$limit,$dbname,$collection);
var_dump($res);
exit();
}
/**
* 修改
*/
public function update(){
$where = ['name'=>'张三1'];//条件
$data = ['name'=>'张三a','age'=>50];//要修改的数据
$multi = true;//批量
$dbname = '';//为空则取默认库
$collection = '';//为空则取默认集合
$res = $this->mongodbUtil->update($where,$data,$multi,$dbname,$collection);
var_dump($res);
exit();
}
/**
* 查询
*/
public function select(){
$dbname = '';//为空则取默认库
$collection = '';//为空则取默认集合
$where = [];//条件
$skip = 0;//过前多少条数据
$limit = 0;//查询多少条数据 0表示全部取出
//排序
$sort = ['age'=>1];//1为升序,-1为降序
//基本查询
$where = ['name'=>'张三a'];
$res = $this->mongodbUtil->select($where,$skip,$limit,$sort,$dbname,$collection);
echo "======基本查询=====\r\n";
print_r($res);
echo "\r\n\r\n\r\n\r\n";
//表达式查询
$where = ['age' => ['$gt' => 52]];
$res = $this->mongodbUtil->select($where,$skip,$limit,$sort,$dbname,$collection);
echo "======表达式查询=====\r\n";
print_r($res);
echo "\r\n\r\n\r\n\r\n";
//or查询
// $where = ['$or' => [['age' => ['$gt' => 50]], ['age' => ['$lt' => 53]]]];
$where = ['$or' => [['age' => ['$gt' => 50]], ['name' => '张三a']]];
$res = $this->mongodbUtil->select($where,$skip,$limit,$sort,$dbname,$collection);
echo "======or查询=====\r\n";
print_r($res);
echo "\r\n\r\n\r\n\r\n";
}
/**
* 只取一条
*/
public function find(){
$dbname = '';//为空则取默认库
$collection = '';//为空则取默认集合
$where = ['name'=>'张三a'];//条件
//排序
$sort = ['age'=>1];//1为升序,-1为降序
$res = $this->mongodbUtil->find($where,$sort,$dbname,$collection);
print_r($res);
}
/**
* 获取总数
*/
public function count(){
$dbname = '';//为空则取默认库
$collection = '';//为空则取默认集合
//条件参数
$where = ['name'=>'张三a'];
$res = $this->mongodbUtil->count($where,$dbname,$collection);
if($res['code']==200){
echo "count:".$res['data'];
}else{
print_r($res);
}
}
/**
* 分页例子
* page_size=1&page=2
*/
public function page(){
$dbname = '';//为空则取默认库
$collection = '';//为空则取默认集合
//分页参数
$page = intval(input('page',1));
if($page<=0) $page = 1;
$page_size = intval(input('page_size',10));
if($page_size<=0) $page_size = 10;
//条件参数
$where = ['name'=>'张三a'];
//排序
$sort = ['age'=>-1];//1为升序,-1为降序
//组合参数,调用mongodb操作类
$start = ($page-1)*$page_size;//越过前多少条数据
$limit = $page_size;
$res = $this->mongodbUtil->select($where,$start,$limit,$sort,$dbname,$collection);
print_r($res);
}
}
以上,希望能对你有所帮助。