7

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 tablesshow 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" }] }) 新建用户设置账户密码,并指定级别。

clipboard.png

关于授权:

  • roles:指定用户的角色,可以用一个空数组给新用户设定空角色;在roles字段,可以指定内置角色和用户定义的角色。

    • **role里的可选角色**

      • Built-In Roles(内置角色)

        1. 数据库用户角色:read、readWrite;
        2. 数据库管理角色:dbAdmin、dbOwner、userAdmin;
        3. 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
        4. 备份恢复角色:backup、restore;
        5. 所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
        6. 超级用户角色:root (有几个角色间接或直接提供了系统超级用户的访问(dbOwner 、userAdmin、userAdminAnyDatabase))
        7. 内部角色:__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,是认证成功。命令可以正常执行。

clipboard.png

注意:MongoDB创建用户在命令行下,并且制定用户可以操作那些库

7. PHP连接MongoDB

Windows 安装 MongoDB PHP扩展
MongoDB PHP扩展下载地址
'Thread safe'(线程安全)是运行在Apache上以模块的PHP上,如果你以CGI的模式运行PHP,请选择非线程安全模式(' non-thread safe')。
版本选择参考:

clipboard.png

clipboard.png

下载完你需要的二进制包后,解压压缩包,将'php_mongo.dll'文件添加到你的PHP扩展目录中(ext)。ext目录通常在PHP安装目录下的ext目录。然后php.ini中打开

clipboard.png

重启服务器。

通过浏览器访问phpinfo,如果安装成功,就会看到类型以下的信息:

clipboard.png

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


参考:菜鸟教程
MongoDB中文社区
MongoDB官方文档


Rango
315 声望22 粉丝

编程是技能 (Skill),不是知识 (Knowledge),技能只有在不断练习下才会有进步。