介绍
介绍
MongoDB是一个文档数据库引擎,文档数据库和MySQL这种关系型数据库是不一样的设计,文档数据库和Redis这种Key-Value数据库也有很大差别。不过文档数据库和Key-Value数据库都属于NoSQL型的数据库,也就是说MongoDB也是不支持SQL语句的。
MongoDB相对于MySQL数据库来说有一项独有的非常强大的特点,就是MongoDB的数据表结构是自由的,可以针对每一个文档(一行数据)定义不同的字段。
MongoDB的文档的存储格式是主流的数据个数JSON,JSON数据是可以设计成一个树状结构的,可以将一个对象的属性以及子属性、孙属性甚至更具体的属性保存到一个JSON数据当中,而MongoDB的一个文档就可以保存它,而无需事先设计好数据表结构来适应这种对象。
基本信息
安装环境
CentOS:CentOS Linux release 7.6.1810 (Core)
Linux:Linux version 3.10.0-1062.el7.x86_64
GCC:gcc version 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)
软件版本
mongodb-linux-x86_64-rhel70-4.2.2.tgz
准备工作
本地化
timedatectl set-timezone Asia/Shanghai
安装wget
如果环境里没有wget,通过yum安装一下
yum -y install wget
安装依赖包
yum -y install libaio numactl-libs
建立环境根目录
mkdir -p /tongfu.net/env/
建立安装包目录并进入
mkdir /packages cd /packages
安装MongoDB 4.2
官网下载
从官网下载
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.2.2.tgz
网盘下载
如果官网下载太慢,可以从网盘下载
链接: https://pan.baidu.com/s/1KjL759qM81Ix_ZRZZxdepg 提取码: yvpi
安装
设置mongo环境变量
[root@tfdev env]# vi /etc/profile export MONGODB_HOME=/tongfu.net/env/mongodb-4.2.2 export PATH=$MONGODB_HOME/bin:$PATH
立即启用环境变量
source /etc/profile
创建用户
useradd mongo
解压缩
tar -xzvf mongodb-linux-x86_64-rhel70-4.2.2.tgz -C /tongfu.net/env/ cd /tongfu.net/env/ mv mongodb-linux-x86_64-rhel70-4.2.2/ mongodb-4.2.2
建立数据目录
mkdir /tongfu.net/env/mongodb-4.2.2/conf mkdir /tongfu.net/env/mongodb-4.2.2/data mkdir /tongfu.net/env/mongodb-4.2.2/logs
建立配置文件
[root@tfdev env]# vi /tongfu.net/env/mongodb-4.2.2/conf/mongodb.conf dbpath = /tongfu.net/env/mongodb-4.2.2/data/ logpath = /tongfu.net/env/mongodb-4.2.2/logs/mongodb.log bind_ip = 0.0.0.0 wiredTigerCacheSizeGB = 2 auth = true journal = true
设置权限
chown mongo.mongo -R /tongfu.net/env/mongodb-4.2.2/
自动启动
添加自动启动脚本
[root@tfdev env]# cat > /lib/systemd/system/mongod.service <<EOF [Unit] Description=mongod After=network.target [Service] Type=forking User=mongo Group=mongo ExecStart=/tongfu.net/env/mongodb-4.2.2/bin/mongod -f /tongfu.net/env/mongodb-4.2.2/conf/mongodb.conf --fork ExecStop=/tongfu.net/env/mongodb-4.2.2/bin/mongod -f /tongfu.net/env/mongodb-4.2.2/conf/mongodb.conf --shutdown PrivateTmp=true [Install] WantedBy=multi-user.target EOF
运行自动启动
systemctl enable mongod # 设置自动启动 systemctl start mongod # 启动服务 systemctl stop mongod # 停止服务 systemctl restart mongod # 重启服务
服务命令添加到系统目录
ln -s /tongfu.net/env/mongodb-4.2.2/bin/mongo /usr/bin/
连接数据库admin
首次登录,无需用户名和密码,直接连接 admin 数据库
/tongfu.net/env/mongodb-4.2.2/bin/mongo 127.0.0.1:27017/admin
创建超级用户
设置超级用户root
db.createUser( { user:"root", pwd:"abcdef", roles: [ { role:"readWriteAnyDatabase", db:"admin" }, { role:"userAdminAnyDatabase", db:"admin" }, { role:"dbAdminAnyDatabase", db:"admin" } ] } );
重新连接数据库admin
使用超级用户root连接数据库admin
/tongfu.net/env/mongodb-4.2.2/bin/mongo -uroot -pabcdef 127.0.0.1:27017/admin
创建数据库
创建数据 field
use field
插入一条数据到表 field
db.field.insert({"id":1,"uName":"萝卜","age":21})
查询表 field 的所有数据
db.field.find()
插入一条数据到表 logs
db.logs.insert({"id":1,"event":"create record"})
查看所有数据库
show dbs
查看所有数据表(集合)
show collections
总结
mongodb的数据库其实就是一个根文件夹
mongodb的数据表就是根文件夹下的子文件夹
mongodb的数据行就是子文件夹下的一个文件,多行数据就是多个文件
mongodb的数据没有字段概念,就是一个大JSON数据结构,也就是一个字符串
mongodb提供了很多方法去查询这些数据
数据导出/导入
导出数据
通过下面的命令导出整个数据库
mongodump -u $user -p $passwd -h $host --port $port -d $dbname -o $backupDir
导入数据
通过下面的命令恢复整个数据库
注意:备份出来的目录下面会有备份的数据库的文件夹,要指定到这一级才行
mongorestore -u $user -p $passwd -h $host --port $port -d $dbname $backupDir/$dbname
MongoDB用户管理
创建用户
使用无认证模式启动mongod
选择admin数据库
use admin
创建root用户
db.createUser( { user:"root", pwd:"123456", roles: [ { role:"userAdminAnyDatabase", db:"admin" },{ role:"dbAdminAnyDatabase", db:"admin" },{ role:"readWriteAnyDatabase", db:"admin" } ] } )
使用认证模式重启mongod
用root登录到admin
/tongfu.net/env/mongodb-3.6.2/bin/mongo -u root -p 123456 admin
选择test数据库
use test
为test库创建用户test
db.createUser( { user:"test", pwd:"123456", roles: [ { role:"dbAdmin", db:"test" },{ role:"readWrite", db:"test" } ] } )
退出root登录
使用test登录到test
/tongfu.net/env/mongodb-3.6.2/bin/mongo -u test -p 123456 test
修改用户
用root登录到admin
/tongfu.net/env/mongodb-3.6.2/bin/mongo -u root -p 123456 admin
选择test数据库
use test
修改密码
db.updateUser( 'test', { pwd:"654321" } )
删除用户
用root登录到admin
/tongfu.net/env/mongodb-3.6.2/bin/mongo -u root -p 123456 admin
选择test数据库
use test
删除test(居然可以删自己!!!)
db.dropUser('test')
查看用户列表
1、登录到admin数据库
2、选择admin数据库
use admin
3、查看用户列表
db.system.users.find()
总结
创建、修改、删除用户必须有权限
用户可以删除自己!!!
调整哪个库的用户表要先选择哪个库
查看用户列表必须到admin库下操作
建议弄一个root超级用户,然后给每个库一个独立账号
用户角色
Read:允许用户读取指定数据库 readWrite:允许用户读写指定数据库 dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile userAdmin:允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户 clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。 readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限 readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限 userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限 dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。 root:只在admin数据库中可用。超级账号,超级权限
坑爹一
认证失败的解决方法
刚刚安装好的环境,使用MongoClient去连接服务器,结果死活报认证错误。
明明是正确的用户名,密码,数据啊~~
从网上查发现旧版本的mongo扩展用的是 MONGODB-CR认证方式。
而最新版的MongoDB服务器得用Scram-SHA-1认证方式
好吧,升级mongo扩展到1.6.13,解决了~~
TFAPI操作MongoDB的方法
示例
// 引入adodbj包,adodbj为JSON行数据库的统称 linking('dbj.adodbj'); // 连接MongoDB服务器 $myDbjObj = new adodbj("driver=mongo;server=localhost;port=27017;uid=field;pwd=abcdef;database=field;charset=utf-8;"); // 查看数据库列表(需要有访问admin的权限) //$dbArr = $myDbjObj->getDbs(); var_dump($dbArr); $condArr = array( 'domainName'=>array('$regex'=>"ali213" ,'$options'=>"iq"), ); // 查询数据数量 $ret = $myDbjObj->count("urls", $condArr); $this->showRet($ret, "count"); // 查询所有数据 $ret = $myDbjObj->search("urls", $condArr, 0, 10, array('_id'=>-1, 'domainName'=>-1)); foreach ($ret as $itm){ $this->showRet($itm, "search"); } // 添加记录,ID为1 $ret = $myDbjObj->add("urls", array('domainName'=>"www.ali213.net ". rand(1111, 9999) ), 1); $this->showRet($ret, "add"); // 手动添加1000条数据,ID为1+$i for($i=0;$i<1000;$i++){ $ret = $myDbjObj->mod("urls", $i+1, array('domainName'=>"www.ali213.net ". rand(1111, 9999), 'idx'=>rand(111, 999) ) ); ///$this->showRet($ret, "mod"); } // 通过mod修改一条数据,ID为1 $ret = $myDbjObj->modRange("urls", array('_id'=>1), array('weight'=>33)); $this->showRet($ret, "modRange"); // 查看数据,ID为1 $ret = $myDbjObj->get("urls", 1); $this->showRet($ret, "get"); // 查看索引 $ret = $myDbjObj->getIndexes("urls"); $this->showRet($ret, "get indexes"); // 创建索引 $ret = $myDbjObj->createIndex("urls", array('domainName'=>1)); $this->showRet($ret, "create index"); // 删除索引 $ret = $myDbjObj->dropIndex("urls", array('domainName'=>1)); $this->showRet($ret, "drop index"); // 清除所有索引 $ret = $myDbjObj->dropIndexes("urls"); $this->showRet($ret, "drop indexes");
TFAPI操作MongoDB的方法(新)
概念
新版本的MongoDB驱动完全变了样,一般情况下我们还是喜欢用旧版本的对象
怎么办呢?
没有关系,官方提供了一个第三方PHP库,封装了新版本的PHP扩展的对象,和老版本的对象及其相似
我们TFAPI也将这个库引入了进来,放到了 driver/mongo 下
使用技巧
// 引入adodbj包,adodbj为JSON行数据库的统称 linking('dbj.adodbj'); // 连接MongoDB服务器,注意:这里的 driver 是 mongo2 不是 mongo 了!! $myDbjObj = new adodbj("driver=mongo2;server=localhost;port=27017;uid=field;pwd=abcdef;database=field;charset=utf-8;"); // 查看数据库列表(需要有访问admin的权限) //$dbArr = $myDbjObj->getDbs(); var_dump($dbArr); $condArr = array( 'domainName'=>array('$regex'=>"ali213" ,'$options'=>"iq"), ); // 查询数据数量 $ret = $myDbjObj->count("urls", $condArr); $this->showRet($ret, "count"); // 查询所有数据 $ret = $myDbjObj->search("urls", $condArr, 0, 10, array('_id'=>-1, 'domainName'=>-1)); foreach ($ret as $itm){ $this->showRet($itm, "search"); } // 添加记录,ID为1 $ret = $myDbjObj->add("urls", array('domainName'=>"www.ali213.net ". rand(1111, 9999) ), 1); $this->showRet($ret, "add"); // 手动添加1000条数据,ID为1+$i for($i=0;$i<1000;$i++){ $ret = $myDbjObj->mod("urls", $i+1, array('domainName'=>"www.ali213.net ". rand(1111, 9999), 'idx'=>rand(111, 999) ) ); ///$this->showRet($ret, "mod"); } // 通过mod修改一条数据,ID为1 $ret = $myDbjObj->modRange("urls", array('_id'=>1), array('weight'=>33)); $this->showRet($ret, "modRange"); // 查看数据,ID为1 $ret = $myDbjObj->get("urls", 1); $this->showRet($ret, "get"); // 查看索引 $ret = $myDbjObj->getIndexes("urls"); $this->showRet($ret, "get indexes"); // 创建索引,只能一个一个创建了 $ret = $myDbjObj->createIndex("urls", array('domainName'=>1)); $this->showRet($ret, "create index 1"); $ret = $myDbjObj->createIndex("urls", array('visits'=>2)); $this->showRet($ret, "create index 2"); // 删除索引,只能一个一个删除了 $ret = $myDbjObj->dropIndex("urls", 'domainName_1'); $this->showRet($ret, "drop index 1"); $ret = $myDbjObj->dropIndex("urls", 'visits_2'); $this->showRet($ret, "drop index 2"); // 清除所有索引 $ret = $myDbjObj->dropIndexes("urls"); $this->showRet($ret, "drop indexes");
MongoDB查询技巧
第一批
// 特殊查询语句示例 // select * from urls where url = 'http://tfapi.tongfu.net/' $myDbjObj->search("urls", array('url'=>"http://tfapi.tongfu.net/")); // select * from urls where url like 'tongfu.net' $myDbjObj->search("urls", array('url'=>array('$regex'=>"tongfu.net"))); // select * from urls where visit > 100 and visit < 1000 $myDbjObj->search("urls", array('visit'=>array('$gt'=>100, '$lt'=>1000))); // select * from urls where weight between 3 and 5 $myDbjObj->search("urls", array('weight'=>array('$gte'=>3, '$lte'=>5))); // select * from urls where urlType <> 'res' $myDbjObj->search("urls", array('urlType'=>array('$ne'=>"res"))); // select * from urls where urlMediaType in ('avi', 'rmvb', 'rm') $myDbjObj->search("urls", array('urlMediaType'=>array('$in'=>array("avi","rmvb","rm")))); // select * from urls where urlMediaType not in ('mov', 'mp4') $myDbjObj->search("urls", array('urlMediaType'=>array('$nin'=>array("mov","mp4")))); // select * from urls where catchTool = 'bd' or catchTimes > 0 $myDbjObj->search("urls", array('$or'=>array('catchTool'=>"bd", 'catchTimes'=>array('$gt'=>0)))); $myDbjObj->search("urls", array('urlExtension'=>array('$all'=>array("img","js","css"))));
第二批
// select * from urls where (_id mod 5) = 1 $myDbjObj->search("urls", array('_id'=>array('$mod'=>array(5, 1)))); // select * from urls where not (catchTimes < 100) $myDbjObj->search("urls", array('$not'=>array('catchTimes'=>array('$lt', 100)))); // 数组中元素同时包含full head $myDbjObj->search("urls", array('catchType'=>array('$all'=>array('full', 'head')))); // 数组中第2个元素为head $myDbjObj->search("urls", array('catchTypes.1'=>"head")); // 数组元素个数是5个 $myDbjObj->search("urls", array('catchTypes'=>array('$size'=>5))); // 嵌套查询 $myDbjObj->search("urls", array('catchInfo.status'=>"fail", 'catchInfo.datetime'=>"2018-1-26 15:12:11")); // 嵌套查询,假定元素是数组的情况下 $myDbjObj->search("urls", array('catchInfo',array('$elemMatch'=>array('status'=>"fail", 'datetime'=>"2018-1-26 15:12:11")))); // 复杂查询情况(这种方式效率比较慢) // 尽量依照 正则 > MapReduce > $where 这个顺序设计 $myDbjObj->search("urls", array('$where',"catchTimes > 0 and catchType == 'head'")); $myDbjObj->search("urls", array('$where',"function(){ var result = catchTimes > 0 and catchType == 'head'; return result; }")); // 排序,分页实现 // 根据_id反序排列,同时从100行开始取10行数据 $myDbjObj->search("urls", array(), 100, 10, array('_id'=>-1));
第三批
// 将键weightNum的值进行数字增减操作(只能是数字类型) $ret = $myDbjObj->modRange("urls", array('_id'=>1), array('$inc'=>array('weightNum'=>1))); $this->showRet($ret, "modRange $inc"); // 向满足条件的文档设置键weightStr值为high(支持嵌套,请使用点符号) $ret = $myDbjObj->modRange("urls", array('_id'=>1), array('$set'=>array('weightStr'=>"high"))); $this->showRet($ret, "modRange $set"); // 从满足条件的文档删除键weight.x(支持嵌套,请使用点符号) $ret = $myDbjObj->modRange("urls", array('_id'=>1), array('$unset'=>array('weightStr'=>1))); $this->showRet($ret, "modRange $unset"); // 向满足条件的文档的键weightRecord数组追加元素值为s1(不检查重复性)(支持嵌套,请使用点符号) $ret = $myDbjObj->modRange("urls", array('_id'=>1), array('$push'=>array('weightRecord'=>"s1"))); $this->showRet($ret, "modRange $push"); $ret = $myDbjObj->modRange("urls", array('_id'=>1), array('$push'=>array('weightRecord'=>"s1"))); $this->showRet($ret, "modRange $push"); // 向满足条件的文档的键weightRecord数组追加元素值为s1(检查重复性)(支持嵌套,请使用点符号) $ret = $myDbjObj->modRange("urls", array('_id'=>1), array('$addToSet'=>array('weightRecord'=>"s1"))); $this->showRet($ret, "modRange $addToSet"); // 向满足条件的文档的键weightRecord数组追加一组元素 $ret = $myDbjObj->modRange("urls", array('_id'=>1), array('$addToSet'=>array('weightRecord'=>array('$each'=>array("s1","s2","s3"))))); $this->showRet($ret, "modRange $each"); // 使用$pop对键weightRecord数组进行删除元素操作 // 删除数组最后位置元素 $ret = $myDbjObj->modRange("urls", array('_id'=>1), array('$pop'=>array('weightRecord'=>1))); $this->showRet($ret, "modRange $pop"); // 删除数组最后位置元素 $ret = $myDbjObj->modRange("urls", array('_id'=>1), array('$pop'=>array('weightRecord'=>-1))); $this->showRet($ret, "modRange $pop"); // 删除数组最后位置元素 $ret = $myDbjObj->modRange("urls", array('_id'=>1), array('$pop'=>array('weightRecord'=>0))); $this->showRet($ret, "modRange $pop"); // 删除数组匹配条件的元素 $ret = $myDbjObj->modRange("urls", array('_id'=>1), array('$pull'=>array('weightRecord'=>"s2"))); $this->showRet($ret, "modRange $pull");