MongoDB简介
MongoDB是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。在高负载的情况下,添加更多的节点,可以保证服务器性能。
MongoDB将数据存储为一个文档,数据结构由键值对组成,MongoDB类似于JSON对象,字段值可以包含其他文档,数组及文档数组。所有存储在集合中的数据都是BSON格式。BSON是一种类json的一种二进制形式的存储格式,简称Binary JSON。
与关系型数据库相比,面向文档的数据库不再有”行”的概念,取而代之的是更为灵活的”文档”模型,通过在文档中嵌入文档和数组,面向文档的方法能够仅使用一条记录来表现复杂的层次关系。
另外,不再有预定义模式:文档的键和值不再是固定的类型和大小。由于没有固定的模式,根据需要添加或删除字段变得更容易了。
MongoDB安装连接
首先去官网http://www.mongodb.org/downloads 下载合适的安装包,运行安装到自定义目录。然后创建数据目录,MongoDB将数据目录存储在db目录下,但是这个数据目录不会主动创建,在安装完成后创建一个data的目录然后在该目录下创建db目录。
命令行下运行MongoDB服务器
打开一个CMD窗口,cd 到MongoDB目录下的bin目录中,运行如下命令:
mongod.exe --dbpath e:\data\db
MongoDB后台管理Shell
另开一个CMD窗口,cd 到bin目录下,然后执行mongo.exe文件,MongoDB Shell是MongoDB自带的交互式JavaScript shell,用来对MongoDB进行操作和管理的交互式环境。进入到MongoDB后台后,默认会连接到test数据库:
E:\MongoDB\bin>mongo
MongoDB shell version v3.4.1
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.1
> db
test
>
MongoDB基本概念
SQL术语 | MongoDB术语 | 说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | 表连接,MongoDB不支持 | |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
MongoDB CRUD操作
数据库的创建删除
创建数据库的语法如下:
use DATABASE_NAME
如果数据不存在,则创建数据库,否则切换到指定数据库。
删除数据库的语法如下:
db.dropDatabase()
删除当前数据库,可以使用db
命令查看当前书数据库名。
创建操作
创建或插入操作即向集合添加新的文档,如果插入时集合不存在,插入操作会创建该集合。
MongoDB提供了如下方法向集合插入文档:
- db.collection.insertOne()
- db.collection.insertMany()
- db.collection.insert()
前俩个方法在3.2的版本引入。这里重点看第三个方法。
在MongoDB中,存储于集合中的文档需要一个唯一的 _id
字段作为 primary key,如果文档中未指定 _id
字段,MongoDB将使用 ObjectId 作为_id
字段的默认值;也就是说,如果文档在插入时没有包含顶层的 _id
字段,MongoDB驱动将添加持有 ObjectId 的_id
字段。
db.collection.insert() 向集合插入一个或多个文档,要想插入一个文档,传递一个文档给该方法;要想插入多个文档,传递文档数组给该方法。
db.user.insert(
{
name: "htdwade",
age: 22,
addr: "深圳"
}
)
db.user.insert(
[
{name:"mike", age:18, addr:"a"},
{name:"tracy", age:20, addr:"b"},
{name:"chris", age:30, addr:"c"}
]
)
读操作
读操作获取集合中的文档;例查询一个集合中的文档,MongoDB提供了如下方法从集合中读取文档:
db.collection.find(<query>,<projection>)
projection以文档的形式列举结果集中要包含或者排除的字段。可以指定要包含的字段(例如:{field:1})或者指定要排除的字段(例如:{field:0})。默认_id是包含在结果集合中的,要从结果集中排除_id字段,需要在projection中指定排除_id字段。
find() 方法以非结构化的方式来显示所有文档。
如果需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:
- db.collection.find().pretty()
MongoDB与RDBMS Where语句比较
操作 | 范例 | RDBMS |
---|---|---|
等于 | db.user.find({“name”:”htdwade”}) .pretty() |
where name=”htdwade” |
小于 | db.user.find({“age”:{$lt:30}}).pretty() | where age<30 |
小于或等于 | db.user.find({“age”:{$lte:30}}).pretty() | where age <=30 |
大于 | db.user.find({“age”:{$gt:20}}).pretty() | where age>20 |
大于或等于 | db.user.find({“age”:{$gte:20}}).pretty() | where age >=20 |
不等于 | db.user.find({“age”:{$ne:20}}).pretty() | where age!=20 |
MongoDB AND条件
MongoDB 的 find() 方法可以传入多个键,每个键以逗号隔开,即常规 SQL 的 AND 条件。
db.collection.find({key1:value1,key2:value2}).pretty()
MongoDB OR条件
MongoDB OR 条件语句使用了关键字 $or,语法格式如下:
db.collection.find(
{
$or:[{key1:value1},{key2:value2}]
}
).pretty()
更新操作
更新操作修改集合中已经存在的文档,MongoDB提供了以下方法去更新集合中的文档:
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
参数说明:
- query: update的查询条件,类似sql update查询内where后面的。
- update: update的对象和一些更新的操作符等,也可以理解为sql update查询内set后面的。
- upsert: 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
- multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
- writeConcern :可选,抛出异常的级别。
示例:
db.user.update(
{"name":"htdwade"},
{$set:{"age":23}},
{multi:false}
)
删除操作
MongoDB remove()函数是用来移除集合中的数据。
remove() 方法的基本语法格式如下所示:
db.collection.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
参数说明:
- query: (可选)删除文档的条件。
- justOne : (可选)如果设为 true 或 1,则只删除第一个找到的文档。
- writeConcern :(可选)抛出异常的级别。
示例:
db.user.remove(
{"name":"htdwade"},
{justOne:1}
)
更多操作符与方法
- type操作符
$type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果。
db.collection.find({"key" : {$type : number}})
number为1时,代表key为Double类型,为2时,代表key为String类型,更多类型请参考MongoDB $type 操作符
- limit()方法
limit()方法接受一个数字参数,该参数指定从MongoDB中读取的记录条数。
db.collection.find().limit(number)
- skip()方法
skip()方法来跳过指定数量的数据,skip方法同样接受一个数字参数作为跳过的记录条数。
db.collection.find().limit(number).skip(number)
- sort()方法
sort()方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而-1是用于降序排列。
db.collection.find().sort({key:1})
MongoDB复制和分片
MongoDB复制
MongoDB复制是将数据同步在多个服务器的过程。
复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性。
复制原理:
mongodb的复制至少需要两个节点。其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据。
mongodb各个节点常见的搭配方式为:一主一从、一主多从。
主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。
MongoDB复制结构图如下所示:
副本集特征:
- N个节点的集群
- 任何节点可作为主节点
- 所有写入操作都在主节点上
- 自动故障转移
- 自动恢复
MongoDB的副本集(复制)与我们常见的主从有所不同,主从在主机宕机后所有服务将停止,而副本集在主机宕机后,副本会接管主节点成为主节点,不会出现宕机的情况。
MongoDB分片
在MongoDB里面存在另一种集群,就是分片技术,可以满足MongoDB数据量大量增长的需求。
当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量。这时,我们就可以通过在多台机器上分割数据,使得数据库系统能存储和处理更多的数据。
在MongoDB中使用分片集群结构分布:
mongos
数据库集群请求的入口,所有的请求都通过mongos进行协调,不需要在应用程序添加一个路由选择器,mongos自己就是一个请求分发中心,它负责把对应的数据请求转发到对应的shard服务器上。在生产环境通常有多mongos作为请求的入口,防止其中一个挂掉所有的mongodb请求都没有办法操作。Config Server
顾名思义为配置服务器,存储所有数据库元信息(路由、分片)的配置。mongos本身没有物理存储分片服务器和数据路由信息,只是缓存在内存里,配置服务器则实际存储这些数据。mongos第一次启动或者关掉重启就会从 config server 加载配置信息,以后如果配置服务器信息变化会通知到所有的 mongos 更新自己的状态,这样 mongos 就能继续准确路由。在生产环境通常有多个 config server 配置服务器,因为它存储了分片路由的元数据,这个可不能丢失!就算挂掉其中一台,只要还有存货, mongodb集群就不会挂掉。shard
这就是传说中的分片了。在mongodb集群只要设置好了分片规则,通过mongos操作数据库就能自动把对应的数据操作请求转发到对应的分片机器上。在生产环境中分片的片键可要好好设置,这个影响到了怎么把数据均匀分到多个分片机器上,不要出现其中一台机器分了1T,其他机器没有分到的情况,这样还不如不分片!实际生产环境中一个shard server角色可由几台机器组个一个replica set承担,防止主机单点故障。
PHP连接MongoDB
首先安装PHP MongoDB扩展,运行phpinfo()查看PHP的版本信息,决定扩展文件版本.
在http://pecl.php.net/package/mongo/1.6.14/windows
下载正确版本的php_mongo.dll动态链接库文件 ,并放在php\ext目录下 。
编辑php.ini,添加下面代码到php.ini文件中。
extension=php_mongo.dll
在phpinfo中查看mongodb扩展是否安装成功:
新建一个PHP文件用来测试:
<?php
$m = new MongoClient(); // 连接
$db = $m->mydb; // 获取名称为 "test" 的数据库
$collection = $db->createCollection("mytest");
echo "mytest集合创建成功";
$document = array(
"name"=>"htdwade",
"age"=>22,
"like"=>"coding"
);
$collection->insert($document);
echo "集合数据插入成功\n";
$ret = $collection->find();
foreach ($ret as $document) {
echo $document["name"] . "\n";
}