首页 > 主页 > 鬼谷子叔叔
日志:116 评论:13
北京, 西城
【MongoDB】MongoDB学习笔记

准备工作

本地化

如果是新环境,我们需要设置时区以保证时间显示正确

timedatectl set-timezone Asia/Shanghai

安装wget

如果环境里没有wget,通过yum安装一下

yum -y install wget

安装gcc

如果环境里没有编译工具,通过yum安装一下

yum -y install gcc gcc-c++ make

安装依赖包

yum -y install libaio numactl-libs

建立环境根目录

mkdir -p /tongfu.net/env/

建立安装包目录并进入

mkdir /packages
cd /packages

安装Linux版本

安装步骤

从官网找到下载链接

官网下载页面 https://www.mongodb.com/download-center?jmp=nav#community 

linux版本 https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.0.0.tgz  

下载

wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.0.0.tgz

安装

tar -xzvf mongodb-linux-x86_64-rhel70-4.0.0.tgz -C /tongfu.net/env/
mv /tongfu.net/env/mongodb-linux-x86_64-rhel70-4.0.0/ /tongfu.net/env/mongodb-4.0.0/

环境变量

设置mongo环境变量

[root@tongfunet]# vi /etc/profile

export MONGODB_HOME=/tongfu.net/env/mongodb-4.0.0
export PATH=$MONGODB_HOME/bin:$PATH

立即启用环境变量

source /etc/profile

创建用户

useradd mongo

建立数据目录

mkdir /tongfu.net/env/mongodb-4.0.0/conf
mkdir /tongfu.net/env/mongodb-4.0.0/data
mkdir /tongfu.net/env/mongodb-4.0.0/logs

配置文件

[root@tongfunet]# vi /tongfu.net/env/mongodb-4.0.0/conf/mongodb.conf

dbpath = /tongfu.net/env/mongodb-4.0.0/data/

logpath = /tongfu.net/env/mongodb-4.0.0/logs/mongodb.log

bind_ip = 0.0.0.0

wiredTigerCacheSizeGB = 2

auth = true

journal = true

自动启动(CentOS7)

添加自动启动脚本

[root@tongfunet]# cat > /lib/systemd/system/mongod.service <<EOF
[Unit]
Description=mongod
After=network.target
 
[Service]
Type=forking
ExecStart=/tongfu.net/env/mongodb-4.0.0/bin/mongod -f /tongfu.net/env/mongodb-4.0.0/conf/mongodb.conf --fork
ExecStop=/tongfu.net/env/mongodb-4.0.0/bin/mongod -f /tongfu.net/env/mongodb-4.0.0/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.0.0/bin/mongo /usr/bin/

创建超级用户

选择数据库admin

use admin

设置超级用户root

db.createUser(
	{
		user:"root",
		pwd:"abcdef",
		roles: [
			{ role:"readWriteAnyDatabase", db:"admin" },
			{ role:"userAdminAnyDatabase", db:"admin" },
			{ role:"dbAdminAnyDatabase", db:"admin" }
		]
	}
);

安装MongoDB的php扩展

安装Linux版本扩展

下载编译扩展包

wget http://pecl.php.net/get/mongodb-1.5.2.tgz
tar -xzvf mongodb-1.5.2.tgz
cd mongodb-1.5.2
/tongfu.net/env/php-7.2.8/bin/phpize
./configure --with-php-config=/tongfu.net/env/php-7.2.8/bin/php-config
make && make install
cd ..

安装扩展

将dll包放入php的extendsion目录下,在php.ini里添加一行代码

extension=mongodb

验证方法

安装成功后通过phpinfo可以看到如下内容

如果看不到的话,证明没有安装成功!注意PHP版本要和扩展要求的版本一致!

创建数据库 field

use field

插入数据

db.field.insert({"id":1,"uName":"萝卜","age":21})

查看数据

db.field.find()

再插入一个表

db.logs.insert({"id":1,"event":"create record"})

查看数据表(集合)

show collections

总结

  1. mongodb的数据库其实就是一个根文件夹

  2. mongodb的数据表就是根文件夹下的子文件夹

  3. mongodb的数据行就是子文件夹下的一个文件,多行数据就是多个文件

  4. mongodb的数据没有字段概念,就是一个大JSON数据结构,也就是一个字符串

  5. 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()

总结

  1. 创建、修改、删除用户必须有权限

  2. 用户可以删除自己!!!

  3. 调整哪个库的用户表要先选择哪个库

  4. 查看用户列表必须到admin库下操作

  5. 建议弄一个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");