1.MongoDB 简介
MongoDB 是由C++语言编写的,是一个基于分布式文件存储
的开源数据库系统。
在高负载的情况下,添加更多的节点,可以保证服务器性能。
MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB 将数据存储为一个文档
,数据结构由键值(key=>value)对
组成。MongoDB 文档类似于JSON对象。字段值可以包含其他文档,数组及文档数组。
2. MongoDB 术语概念
MongoDB 和关系型数据库相关概念关系对照表:
SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table | joins | 表连接,MongoDB不支持 |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
3. MongoDB shell 常用命令
use DATABASE_NAME
:如果数据库不存在,则创建数据库,否则切换到指定数据库
db.getName()
或db
:当前正在使用的数据库
show dbs
:查询所有数据库
db.dropDatabase()
:删除当前数据库,默认为 test。其他库先切换。
db.collection.drop()
:删除集合。collection为集合名称。
show tables
或show collection
:查询当前库下所有集合。
db.createCollection(name, options)
:创建集合。name
: 要创建的集合名称;options
: 可选参数, 指定有关内存大小及索引的选项.例:db.createCollection("runoob")
如果 mongo shell不接受集合的名称,例如如果名称中包含空格,连字符”-“,或者以数字开始,你可以使用代替语法来指代集合,如下所示:
>db["3test"].find() db.getCollection("3test").find()
db.stats()
查看数据库使用状态的统计信息。
>db.stats()
{
"db":"test",
--查看的是哪个数据库
"collections":7,
--collection数量
"objects":28,
--当前数据库中所有集合中的对象数(即文档)的数量。
"avgObjSize":50.57142857142857,
--对象平均大小,以字节为单位
"dataSize":1416,
--数据大小
"storageSize":31744,
--数据大小(含预分配空间)
"numExtents":7,
--事件数量
"indexes":7,
--索引数量
"indexSize":57344,
--索引大小
"fileSize":50331648,
--文件大小
"ok":1
--本次取stats是否正常
}
4. MongoDB CURD
- 插入(Create)
简述:文档的数据结构和JSON基本一样。所有存储在集合中的数据都是BSON格式。是一种类json的一种二进制形式的存储格式,简称Binary JSON。命令格式如下:db.COLLECTION_NAME.insert(document)
例:
>db.col.insert({title: 'MongoDB 教程',
description: 'MongoDB 是一个 Nosql 数据库',
by: '菜鸟教程',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
})
插入的时候如果集合不存在,那么插入操作会创建集合。
_id
字段:在MongoDB中,存储于集合中的每一个文档都需要一个唯一的 _id 字段作为 primary_key。如果一个插入文档操作遗漏了_id
字段,MongoDB驱动会自动为_id
字段生成一个ObjectId
。
这种情况同样适用于通过带有参数 upsert: true 的update操作来插入文档的情况。
ObjectId
:
MongoDB采用了一个称之为ObjectId的类型来做主键。ObjectId是一个12字节的 BSON 类型字符串,BSON字符串都是UTF-8编码。按照字节顺序,从开头依次表示:
- 4字节:UNIX时间戳
- 3字节:表示运行MongoDB的机器的标识符
- 2字节:表示生成此
_id
的进程- 3字节:由一个随机数开始的计数器生成的值
db.collection.insertOne()
: 向集合插入单个文档。db.collection.insertMany()
: 向集合插入多个文档。
- 更新(Update)
命令格式如下:
db.collection.update(
<query>, // update的查询条件,类似sql update查询内where后面的。
<update>, //update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update 查询内set后面的
{
upsert: <boolean>, //可选,这个参数的意思是,如果不存在'update的记录,是否插入objNew,true为插入,默认是false,不插入
multi: <boolean>, // 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
writeConcern: <document> //可选,抛出异常的级别。
}
)
示例:db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}})
更新一条数据标题(title)。
默认情况下, db.collection.update()
只更新一个文档。要更新多个文档,请使用 multi 选项设置 multi 参数为 true。
save()
方法通过传入的文档来替换已有文档。语法格式如下:
db.collection.save(
<document>,//文档数据。
{
writeConcern: <document> //可选,抛出异常的级别。
}
)
_id
字段一旦设定,你不能更新 _id 字段的值,你也不能用有不同 _id 字段值的替换文档来替换已经存在的文档。
其他命令:db.collection.updateOne()
即使可能有多个文档通过过滤条件匹配到,但是也最多也只更新一个文档。db.collection.updateMany()
更新所有通过过滤条件匹配到的文档。db.collection.replaceOne()
即使可能有多个文档通过过滤条件匹配到,但是也最多也只替换一个文档。
- 查询(Retrieve)
db.collection.find(query, projection)
方法从集合中读取文档,省略过滤条件则是查询所有文档;collection是文档名称。
query :可选,使用查询操作符指定查询条件
projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
db.collection.find().pretty()
:pretty()
方法以格式化的方式来显示所有文档。
除了 find() 方法之外,还有一个 findOne()
方法,它只返回一个文档。
MongoDB 与 RDBMS Where 语句比较
操作 | 格式 | 范例 | RDBMS中的类似语句 |
---|---|---|---|
等于 | {<key>:<value>} | db.col.find({"by":"菜鸟教程"}).pretty() | where by = '菜鸟教程' |
小于 | {<key>:{$lt :<value>}} | db.col.find({"likes":{$lt:50}}).pretty() | where likes < 50 |
小于或等于 | {<key>:{$lte :<value>}} | db.col.find({"likes":{$lte:50}}).pretty() | where likes <= 50 |
大于 | {<key>:{$gt :<value>}} | db.col.find({"likes":{$gt:50}}).pretty() | where likes > 50 |
大于或等于 | {<key>:{$gte :<value>}} | db.col.find({"likes":{$gte:50}}).pretty() | where likes >= 50 |
不等于 | {<key>:{$ne :<value>}} | db.col.find({"likes":{$ne:50}}).pretty() | where likes != 50 |
包含 | {<key>:{$in :[a,b,c]} | db.col.find("likes":{$in:[2,4,6]}).pretty() | where likes in(2,4,6) |
不包含 | {<key>:{$nin :[a,b,c]} | db.col.find("likes":{$nin:[2,4,6]}).pretty() | where likes not in(2,4,6) |
MongoDB AND 条件find()
方法可以传入多个键(key),每个键(key)以逗号
隔开,即常规 SQL 的 AND 条件。
db.col.find(
{
"by":"菜鸟教程",
"title":"MongoDB 教程"
}
).pretty()
MongoDB OR 条件
OR 条件语句使用了关键字 $or
,语法格式如下
>db.col.find(
{
$or: [
{key1: value1}, {key2:value2}
]
}
).pretty()
>db.col.find(
{
$or:[
{"by":"菜鸟教程"},
{"title": "MongoDB 教程"}
]
}
).pretty()
AND 和 OR 联合使用
>db.col.find(
{"likes":
{$gt:50},
$or: [
{"by": "菜鸟教程"},
{"title": "MongoDB 教程"}
]
}
).pretty()
projection
参数的使用方法
db.collection.find(query, projection)
若不指定 projection,则默认返回所有键,指定 projection 格式如下,有两种模式
- db.collection.find(query, {title: 1, by: 1}) //
inclusion模式
指定返回的键,不返回其他键- db.collection.find(query, {title: 0, by: 0}) //
exclusion模式
指定不返回的键,返回其他键_id 键默认返回,需要主动指定 _id:0 才会隐藏
两种模式
不可混用
(因为这样的话无法推断其他键是否应返回)db.collection.find(query, {title: 1, by: 0}) // 错误
只能全1或全0,除了在inclusion模式时可以指定_id为0
db.collection.find(query, {_id:0, title: 1, by: 1}) // 正确
- 删除(Delete)
MongoDB remove()
函数是用来移除集合中的数据。在执行remove()
函数前先执行find()
命令来判断执行的条件是否正确,这是一个比较好的习惯。
remove() 方法的基本语法格式如下所示:
db.collection.remove(
<query>, //(可选)删除的文档的条件。
{
justOne: <boolean>, //(可选)如果设为 true 或 1,则只删除一个文档。
writeConcern: <document> //(可选)抛出异常的级别。
}
)
现在官方推荐使用
deleteOne()
和deleteMany()
方法。db.inventory.deleteMany({})
:删除集合下全部文档。例如:
删除 status 等于 A 的全部文档: db.inventory.deleteMany({ status : "A" }) 删除 status 等于 D 的一个文档: db.inventory.deleteOne( { status: "D" } )
5. Windows 下的配置文件及 mongo 进程
安装完成之后,Windows下是不会自动生成配置文件,也没有进程。
新建配置文件
- 在mongodb的安装目录下,如
C:\Program Files\MongoDB\Server\3.6
新建conf
目录并新建mongod.conf
文件,配置内容如下:systemLog: #日志文件 destination: file path: F:\mongoDB\logs\mongod.log logAppend: true storage: #数据存储路径 dbPath: F:\data\db journal: enabled: true net:#绑定ip及端口 bindIp: 127.0.0.1 port: 27017 setParameter: enableLocalhostAuthBypass: true #security:#安全认证 #authorization: enabled
log文件也是不存在的,根据自己的需要在相应的目录下新建
mongod.log
文件。开启认证及生成守护进程
mongod --auth --config "C:\Program Files\MongoDB\Server\3.6\conf\mongod.conf" --install --serviceName "MongoD
--auth : 开启认证
--serviceName "MongoDB":生成名称为MongoDB的守护进程
6. 设置账户密码
特别注意:帐号是跟着库走的,所以在指定库里授权,必须也在指定库里验证(auth)。
配置之前先配置文件不要开启auth
认证,默认为关闭状态。否则进入查看数据库会权限不足。
命令行下执行`mongo
进入数据库
use admin
进入admin库
db.getUsers()
可查看当前库用户列表
执行db.createUser({ user: "admin", pwd: "admin", roles: [{ role: "userAdminAnyDatabase", db: "admin" }] })
新建用户设置账户密码,并指定级别。
关于授权:
-
roles
:指定用户的角色,可以用一个空数组给新用户设定空角色;在roles字段,可以指定内置角色和用户定义的角色。-
**role里的可选角色**
:-
Built-In Roles(内置角色):
- 数据库用户角色:read、readWrite;
- 数据库管理角色:dbAdmin、dbOwner、userAdmin;
- 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
- 备份恢复角色:backup、restore;
- 所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
- 超级用户角色:root (有几个角色间接或直接提供了系统超级用户的访问(dbOwner 、userAdmin、userAdminAnyDatabase))
- 内部角色:__system
-
具体角色权限:
Read
:允许用户读取指定数据库
readWrite
:允许用户读写指定数据库
dbAdmin
:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
userAdmin
:允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户
clusterAdmin
:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。
readAnyDatabase
:只在admin数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase
:只在admin数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase
:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
dbAdminAnyDatabase
:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。
root
:只在admin数据库中可用。超级账号,超级权限
-
-
修改配置文件:sudo vim /etc/mongodb.conf
security:
authorization: enabled
//注意缩进,缩进参照配置文件其他配置。缩进错误可能重启不成功
去掉前面的 # 号。
重启mongo服务
/etc/init.d/mongodb restart
重新进入数据库,发现命令无法执行,报权限不足错误。切换到admin库use admin
(哪里创建的用户切换到哪个库),执行db.auth("admin","admin")
返回1,是认证成功。命令可以正常执行。
注意:MongoDB创建用户在命令行下,并且制定用户可以操作那些库
7. PHP连接MongoDB
Windows 安装 MongoDB PHP扩展
MongoDB PHP扩展下载地址
'Thread safe'(线程安全)是运行在Apache上以模块的PHP上,如果你以CGI的模式运行PHP,请选择非线程安全模式(' non-thread safe')。
版本选择参考:
下载完你需要的二进制包后,解压压缩包,将'php_mongo.dll'文件添加到你的PHP扩展目录中(ext)。ext目录通常在PHP安装目录下的ext目录。然后php.ini中打开
重启服务器。
通过浏览器访问phpinfo,如果安装成功,就会看到类型以下的信息:
Linux上安装 MongoDB PHP扩展
linux中执行以下命令来安装MongoDB 的 PHP7
扩展驱动
$ /usr/local/php7/bin/pecl install mongodb
执行成功后,会输出以下结果:
……
Build process completed successfully
Installing '/usr/local/php7/lib/php/extensions/no-debug-non-zts-20151012/mongodb.so'
install ok: channel://pecl.php.net/mongodb-1.1.7
configuration option "php_ini" is not set to php.ini location
You should add "extension=mongodb.so" to php.ini
下来我们打开 php.ini 文件,添加 extension=mongodb.so 配置。
可以直接执行以下命令来添加。
$ echo "extension=mongodb.so" >> `/usr/local/php7/bin/php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`
注意:以上执行的命令中 php7 的安装目录为 /usr/local/php7/,如果你安装在其他目录,需要相应修改 pecl 与 php 命令的路径。 使用php的
pecl
安装命令必须保证网络连接可用以及root权限。
如果你的php是自己编译的,则安装方法如下(假设是编译在/usr/local/php目录中) github地址:
$ git clone https://github.com/mongodb/mongo-php-driver.git
$ cd mongo-php-driver
$ git submodule sync && git submodule update --init
$ /usr/local/php/bin/phpize
$ ./configure --with-php-config=/usr/local/php/bin/php-config
$ make all -j 5
$ sudo make install
执行以上命令后,你需要修改php.ini
文件,在php.ini文件中添加mongo配置,
配置如下: extension=mongo.so
注意:你需要指明 extension_dir 配置项的路径。
php例子:
<?php
//连接数据库
$manager = new MongoDB\Driver\Manager("mongodb://localhost:27017");
// 插入数据,BulkWrite是批量插入
$bulk = new MongoDB\Driver\BulkWrite;
$bulk->insert(['x' => 1, 'name'=>'菜鸟教程', 'url' => 'http://www.runoob.com']);
$bulk->insert(['x' => 2, 'name'=>'Google', 'url' => 'http://www.google.com']);
$bulk->insert(['x' => 3, 'name'=>'taobao', 'url' => 'http://www.taobao.com']);
$manager->executeBulkWrite('test.sites', $bulk);
$filter = ['x' => ['$gt' => 1]]; //字段名及匹配条件
$options = [
'projection' => ['_id' => 0], // 指定返回键,参考上面**projection用法**
'sort' => ['x' => -1], //排序字段,1是正序,-1是倒序
];
// 查询数据
$query = new MongoDB\Driver\Query($filter, $options);
$cursor = $manager->executeQuery('test.sites', $query);
foreach ($cursor as $document) {
print_r($document);
}
?>
8. MongoDB备份与恢复
在Mongodb中我们使用mongodump
命令来备份
MongoDB数据。该命令可以导出所有数据到指定目录中。
> mongodump -h HOST_NAME -d DB_NAME -o BACKUP_DIRECTORY
> mongodump --host HOST_NAME --port PORT_NUMBER -d DB_NAME -o BACKUP_DIRECTORY
示例:备份单库
vagrant@homestead:~$ mongodump -h 127.0.0.1 -d DB_NAME -o /root/dbBackup/mongoDB/dbBackupName_$(date +"%Y-%m-%d_%H")
也可以备份指定文档:
> mongodump -h dbhost --collection COLLECTION -d DB_NAME -o BACKUP_DIRECTORY
mongodb使用 mongorestore
命令来恢复备份的数据。
>mongorestore -h <hostname><:port> -d dbname <path>
--host
<:port>,-h
<:port>:
MongoDB所在服务器地址,默认为: localhost:27017--db
,-d
:
需要恢复的数据库实例,例如:test,当然这个名称也可以和备份时候的不一样,比如test2--drop
:
恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,这份备份文件之后添加或修改的数据都会被删除,慎用哦!<path>
:
mongorestore 最后的一个参数,设置备份数据所在位置,例如:c:datadumptest。
你不能同时指定 <path> 和 --dir 选项,--dir也可以设置备份目录。--dir
:
指定备份的目录
你不能同时指定 <path> 和 --dir 选项。
示例:
vagrant@homestead:~$ /usr/local/mongodb/bin/mongodump -h 127.0.0.1:27117 -u USER_NAME -p PASSWORD -d DB_NAME -o /BACK_DIRECTORY/BACKUP_DB_NAME
9. 错误
- 没有
phpize
命令
执行: sudo apt install php7.2-dev
- 错误:
The SCRAM_SHA_1 authentication mechanism requires libmongoc built with ENABLE_SSL
方法:
sudo apt-get install -y libcurl4-openssl-dev pkg-config libssl-dev
sudo pecl install mongodb
安装后别忘记在 php.ini 中添加 extension=mongodb.so
重启:sudo service php7.2-fpm restart