目录
一、MongoDB连接
标准的URI连接语法:
mongodb://[username:password@]host1[:port1][,host2[:port2],...,[,hostN[:hostN]][/[database[?options]]
mongodb:// --固定格式,必须指定。
username:password@ --可选项,如果设置,在连接数据库服务器后,驱动都会尝试登录这个数据库。
host1 --必须的指定至少一个host,host1是这个URI必须填写的。它指定了要连接服务器的地址。如果要连接复制集,可以指定多个主机地址。
port --可选指定端口,如果不填,默认27017。
/database --如果指定username:password@,连接并验证登录指定数据库。不指定则默认打开test数据库。
?options --连接选项。如果不使用/database,则前面需加上/。所有连接选项都是键值对name=value,键值对间通过&或; 分隔
标准的连接格式包含多个选项(options),如下:
选项 | 描述 |
---|---|
replicaSet=name | 验证replica set(复制集)的名称。 Impliesconnect=replicaSet. |
slaveOk=true|false |
|
safe=true|false |
|
w=n | 驱动添加 { w : n } 到getLastError命令. 应用于safe=true。 |
wtimeoutMS=ms | 驱动添加 { wtimeout : ms } 到 getlasterror 命令. 应用于 safe=true. |
fsync=true|false |
|
journal=true|false | 如果设置为 true, 同步到 journal (在提交到数据库前写入到实体中). 应用于 safe=true |
connectTimeoutMS=ms | 可以打开连接的时间。 |
socketTimeoutMS=ms | 发送和接受sockets的时间。 |
实例:
1、使用用户名admin和密码123456连接到默认数据库:
mongodb://admin:123456@localhost/
2、连接本地数据库服务器,端口使用默认
mongodb://localhost
3、使用用户名admin和密码123456登录到localhost的baz数据库
mongodb://admin:123456@localhost/baz
4、连接replica pair,服务器1为example1.com,服务器为example2.com
mongodb://exxample1.com:27017,example2.com:27017
5、连接replica set三台服务器(端口27017,27018,27019)
mongodb://localhost, localhost:27018, localhost:27019
6、连接replica set三台服务器,写入操作应用在主服务器并分布查询到从服务器
mongodb://host1, host2, host3/?slaveOk=true
7、直连第一个服务器,无论replica set一部分或者主服务器或从服务器
mongodb://host1, host2, host3/?connect=direct;slaveOk=true
当连接的服务器有优先级时,需列出所有服务器。使用上述连接方式
8、安全连接到localhost
mongodb://localhost/?safe=true
9、以安全模式连接到replica set,并等待至少两个复制服务器成功写入,超时时间设置为2秒
mongodb://host1, host2, host3/?safe=true;w=2;wtimeoutMS=2000
二、创建数据库
语法:use DATABASE_NAME
如果数据库不存在则创建,否则切换到指定数据库。
实例:
1、创建数据库school
use school
2、查看所有数据库
show dbs
由于student数据库没有数据,所以执行show dbs命令时不显示。要显示它需要插入一些数据
3、插入数据
db.student.insert({"name":"小明"})
三、删除数据库
语法:db.dropDatabase()
删除当前数据库,默认为test,可以使用db命令查看当前数据名。
实例:
1、首先查看数据库:
show dbs
2、切换到数据库school:
use school
3、执行删除命令:
db.dropDatabase()
4、最后查看数据库是否被删除
show dbs
四、创建集合
语法:db.createCollection(name, options)
参数说明:
name --集合名
options --可选参数,指定有关内存大小及索引的选项。参数如下:
字段 | 类型 | 描述 |
---|---|---|
capped | 布尔 | (可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。 当该值为 true 时,必须指定 size 参数。 |
autoIndexId | 布尔 | 3.2 之后不再支持该参数。(可选)如为 true,自动在 _id 字段创建索引。默认为 false。 |
size | 数值 | (可选)为固定集合指定一个最大值,即字节数。 如果 capped 为 true,也需要指定该字段。 |
max | 数值 | (可选)指定固定集合中包含文档的最大数量。 |
在插入文档时,mongodb会先检查size,再检查max。
实例:
1、在school数据库中创建student集合(相当于关系型数据库中的table表)
> use school
switched to db school
> db.createCollection("student")
{ "ok" : 1 }
>
查看已有集合,使用show collections 或 show tables:
> show collections
student
system.indexes
2、创建固定集合mycol
集合空间大小为6142800B,文档最大个数为10000个:
db.createCollection("mycol", {capped:true, autoIndexId:true, size:6142800, max:10000})
MongoDB中,无需特定创建集合,当插入文档时,会自动创建:
> db.mycol1.insert({"name":"小明"})
>show collections
mycol1
五、删除集合
语法:db.collection.drop()
返回值:删除成功则返回true,否则false
实例:
先用show collections 命令查看已有集合,接着删除集合mycol1:
> show collections
mycol
mycol1
system.indexes
student
> db.mycol1.drop()
true
六、插入文档
文档数据结构与JSON基本一样,所有存储在集合中的数据都是BSON格式(一种二进制的存储格式)。
语法:
1、db.COLLECTION_NAME.insert(document)
或db.COLLECTION_NAME.save(document)
db.collection.insertOne()或db.collection.replaceOne()
说明:
save()方法:如果_id主键存在则更新数据,不存在则插入数据。该方法以废弃,可以使用db.collection.insertOne()或db.collection.replaceOne()来代替。
insert()方法:若插入的数据主键已经存在,则会抛出主键冲突异常,插入失败。
2、使用或db.collection.insertOne()来插入新文档:
db.collection.insertOne(
<document>,
{
writeConcern: <document>
}
)
3、使用db.collection.insertMany()插入文档:
db.collection.insertMany(
[<document 1>, <document 2>, ...]
{
writeConcern: <document>,
ordered: <boolean>
}
)
参数说明:
document --要写入的文档
writeConcern --写入策略,默认为1,即要求确认写操作,0是不要求
ordered --指定是否按顺序写入,默认为true,按顺序写入
实例1
在数据库school的student集合中插入文档:
1、先将文档数据定位一个变量document
document=({
name : '小明',
sex : 'm',
age : 18,
weight : 100,
subject : ['math', 'English', 'physical']
});
执行后显示:
{
"name" : "小明",
"sex" : "m",
"age" : 18,
"weight" : 100,
"subject" : ["math", "English", "physical"]
}
2、执行插入操作
db.student.insert(document)
实例2
一次插入多条文档数据:
document_list = [{"a" : 1}, {"b" : 2}]
db.collection1.insertMany(document_list)
八、更新文档
1、update()方法
语法:
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>
multi: <boolean>
writeConcern: <document>
}
)
参数说明:
query --update的查询条件,类似sql update中的where后的语句条件。
update --update的对象和一些更新的操作符(如$, $inc,...)也可理解为sql update中set后面的语句
upsert -- 可选,若为true,即不存在update的对象记录时则插入。默认时false,不插入
multi --可选,默认是false,只更新找到的第一条记录。如果为true,就把匹配到的记录全部更新
writeConcern:可选,抛出异常的级别
实例:
更新student集合中文档的name:
db.student.update({'name':'小明'}, {$set: {'name':'小王'}})
修改多条:
db.student.update({'name':'小明'}, {$set: {'name':'小王'}}, {multi: true})
2、save()方法
通过传入文档来替换已有的文档,_id存在就更新,不存在就插入。
语法:
db.collection.save(
<document>,
{
writeConcern: <document>
}
)
参数说明:
document --文档数据
writeConcern --可选,抛出异常的级别
九、删除文档
1、使用remove()方法来删除文档(已过时)。
语法:
db.collection.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
参数说明:
query --可选,删除文档的查询条件
justOne --可选,如果为true或1,则值删除一个文档,不设置的话默认false,则删除所有匹配的文档
writeConcern --可选,抛出异常的级别
实例:
db.student.remove({'name' : '小明'})
删除所有数据(相当于SQL中的truncate命令):
db.student.remove({})
2、deleteOne()和deleteMany()
删除集合全部文档:
db.student.deleteMany({})
删除name为小明的全部文档:
db.student.deleteMany({'name' : '小明'})
删除一个name为小明的文档:
db.student.deleteOne({'name' : '小明'})
十、查询文档
1、find()方法。
语法:
db.collection.find(query, projection)
参数说明:
query --可选,使用查询操作符指定查询条件
projection --可选,使用投影操作符指定返回的键。查询时返回文档中所有的键值,值需要省略该参数即可
易读方式查询数据,使用pretty()方法,格式化显示所有文档:
db.collection.find().pretty()
findOne()方法,只返回一个文档。
2、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 |
3、MongoDB的 and条件
find()方法可以传入多个键,每个键以逗号分隔,即相当于常规SQL的and条件。
语法:
db.col.find({key1:value1, key2:value2}).pretty()
4、MongoDB的or条件
使用关键字 $or ,语法:
db.collection.find(
{
$or: [
{key1: value1}, {key2: value2}
]
}
)
5、and和or联合使用
相当于SQL中的:where likes>50 and (by = '菜鸟教程' or title='MongoDB 教程')
db.col.find({"likes": {$gt:50}, $or: [{"by": "菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty()
十一、条件操作符
MongoDB中条件操作符有:
- (>) 大于 - $gt
- (<) 小于 - $lt
- (>=) 大于等于 - $gte
- (<= ) 小于等于 - $lte
语法:
db.collection.find({key : {$gt : value}}) #key大于value2
db.collection.find({key : {$lt : value}}) #key小于value2
db.collection.find({key : {$gte : value}}) #key大于等于value2
db.collection.find({key : {$lte : value}}) #key小于等于value2
db.collection.find({key : {$lt: value1, $gt: value2}}) #key大于value2,小于value1
十二、$type操作符
$type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果。
MongoDB中科院使用的类型如下所示:
类型 | 数字 | 备注 |
---|---|---|
Double | 1 | |
String | 2 | |
Object | 3 | |
Array | 4 | |
Binary data | 5 | |
Undefined | 6 | 已废弃。 |
Object id | 7 | |
Boolean | 8 | |
Date | 9 | |
Null | 10 | |
Regular Expression | 11 | |
JavaScript | 13 | |
Symbol | 14 | |
JavaScript (with scope) | 15 | |
32-bit integer | 16 | |
Timestamp | 17 | |
64-bit integer | 18 | |
Min key | 255 | Query with -1. |
Max key | 127 |
实例:
获取col集合送title为String的数据,科院使用以下命令:
db.col.find({"title": {$type: 2}})
或
db.col.find({"title": {$type: 'string'}})
十三、Limit方法和Skip方法
1、limit()方法
使用limit()方法来读取指定数量的数据。
语法:
db.collection.find().limit(NUMBER)
参数说明:
NUMBER --查询限制条数
2、skip()方法
使用skip()方法来跳过指定数量的数据。
语法:
db.collection.find().limit(NUMBER).skip(NUMBER)
参数说明:
NUMBER --查询限制或跳过条数
注:skip()方法默认参数为 0 。
十四、排序
sort()方法用来排序,使用1作为升序,-1作为降序条件。
语法:
db.collection.find().sort({KEY:1})
参数说明:
KEY:键,用来排序的字段
十五、索引
1、创建索引 createIndex()方法
语法:
db.collection.createIndex({key1: 1, key2: -1, ...}, options)
参数说明:
keys --用来创建索引的字段,1指定升序创建索引,-1指定降序创建索引
options --可选参数,如下:
Parameter | Type | Description |
---|---|---|
background | Boolean | 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false。 |
unique | Boolean | 建立的索引是否唯一。指定为true创建唯一索引。默认值为false. |
name | string | 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。 |
dropDups | Boolean | 3.0+版本已废弃。在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false. |
sparse | Boolean | 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false. |
expireAfterSeconds | integer | 指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。 |
v | index version | 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。 |
weights | document | 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。 |
default_language | string | 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语 |
language_override | string | 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language. |
实例:
在后台创建唯一索引:
db.collection1.createIndex({open: 1, close: 1}, {background: true, unique: true})
2、查看索引
db.collection.getIndex()
3、查看索引大小
db.collection.totalIndexSize()
4、删除指定索引
db.collection.dropIndex(索引名)
注:利用 TTL 集合对存储的数据进行失效时间设置:经过指定的时间段后或在指定的时间点过期,MongoDB 独立线程去清除数据。类似于设置定时自动删除任务,可以清除历史记录或日志等前提条件,设置 Index 的关键字段为日期类型 new Date()。
例如数据记录中 createDate 为日期类型时:
- 设置时间180秒后自动清除。
- 设置在创建记录后,180 秒左右删除。
db.col.createIndex({"createDate": 1},{expireAfterSeconds: 180})由记录中设定日期点清除。
设置 A 记录在 2019 年 1 月 22 日晚上 11 点左右删除,A 记录中需添加 "ClearUpDate": new Date('Jan 22, 2019 23:00:00'),且 Index中expireAfterSeconds 设值为 0。
db.col.createIndex({"ClearUpDate": 1},{expireAfterSeconds: 0})其他注意事项:
- 索引关键字段必须是 Date 类型。
- 非立即执行:扫描 Document 过期数据并删除是独立线程执行,默认 60s 扫描一次,删除也不一定是立即删除成功。
- 单字段索引,混合索引不支持。
十六、聚合
聚合用于处理数据(如统计平均值,求和等),并返回计算后的数据,类似于SQL中的count(*)。
语法:db.collection.aggregate(aggrefate_operation)
参数说明:
aggregate_operation --操作符,常见如下:
$project:修改输入文档的结构。可以用于重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
$match:用于过滤数据,值输出符合条件的文档,用于标准查询操作。
$limit:用来限制聚合管道返回的文档数。
$sjip:在管道中跳过指定数量的文档,并当余下文档。
$unwind:将文档中的某一个数组类型拆分为多条,每条包含数组一个值。
$group:将集合的文档分组,可用于统计结果。相当于SQL中的group by。
$sort:将输出文档排序。
$geoNear:输出接近某一地理位置的有序文档。
实例:
集合数据:
{
_id: ObjectId(7df78ad8902c)
title: 'MongoDB Overview',
description: 'MongoDB is no sql database',
by_user: 'runoob.com',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
},
{
_id: ObjectId(7df78ad8902d)
title: 'NoSQL Overview',
description: 'No sql database is very fast',
by_user: 'runoob.com',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 10
},
{
_id: ObjectId(7df78ad8902e)
title: 'Neo4j Overview',
description: 'Neo4j is no sql database',
by_user: 'Neo4j',
url: 'http://www.neo4j.com',
tags: ['neo4j', 'database', 'NoSQL'],
likes: 750
},
计算出每个作者缩写的文章数:
> db.mycol.aggregate({$group: {_id: "$by_user", num_tutorial: {$sum: 1}}})
{
"result" : [
{
"_id" : "runoob.com",
"num_tutorial" : 2
},
{
"_id" : "Neo4j",
"num_tutorial" : 1
}
],
"ok" : 1
}
类似于SQL语句:
select by_user, count(*) from mycol group by by_user
聚合表达式:
表达式 | 描述 | 实例 |
---|---|---|
$sum | 计算总和。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}]) |
$avg | 计算平均值 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}]) |
$min | 获取集合中所有文档对应值得最小值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}]) |
$max | 获取集合中所有文档对应值得最大值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}]) |
$push | 将值加入一个数组中,不会判断是否有重复的值。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}]) |
$addToSet | 将值加入一个数组中,会判断是否有重复的值,若相同的值在数组中已经存在了,则不加入。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}]) |
$first | 根据资源文档的排序获取第一个文档数据。 | db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}]) |
$last | 根据资源文档的排序获取最后一个文档数据 | db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}]) |
管道的概念
管道在Unix和Linux中一般用于将当前命令的输出结果作为下一命令的参数。
MongoDB中的聚合管道将文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作时可重复的。
表达式:处理输入文档并输出。表达式无状态,只能用于计算当前管道中的文档,不能处理其他文档。
实例1 $project:
db.article.aggregate(
{ $project : {
title : 1 ,
author : 1 ,
}}
);
结果中就只还有_id,tilte和author三个字段了,默认情况下_id字段是被包含的,如果要想不包含_id话可以这样:
db.article.aggregate(
{ $project : {
_id : 0 ,
title : 1 ,
author : 1
}});
实例2: $match:
db.articles.aggregate( [
{ $match : { score : { $gt : 70, $lte : 90 } } },
{ $group: { _id: null, count: { $sum: 1 } } }
] );
$match用于获取分数大于70小于或等于90记录,然后将符合条件的记录送到下一阶段$group管道操作符进行处理。
实例3 $skip:
db.article.aggregate(
{ $skip : 5 });
经过$skip管道操作符处理后,前五个文档被"过滤"掉。
十七、复制(副本集)
MongoDB的复制是将数据同步在多个服务器的过程。
复制提供数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性,并可保证数据的安全性。复制还允许从硬件故障和服务中断中恢复。
1、复制的优点:
- 保障数据的安全性
- 数据高可用性 (24*7)
- 灾难恢复
- 无需停机维护(如备份,重建索引,压缩)
- 分布式读取数据
2、mongodb复制的原理:
复制至少需要两个节点,一个主节点,负责处理客户端请求,其余从节点,负责复制主节点上的数据。常见的搭配方式为:一主一从、一主多从。
主节点记录其上面所有的操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行相同的操作,从而保证和主节点数据保持一致。
如图所示:
上图所示,客户端从主节点读取数据,在客户端写入数据到主节点时,主节点与从节点进行数据交互保障数据一致性。
3、副本集的特征:
- N 个节点的集群
- 任何节点可作为主节点
- 所有写入操作都在主节点上
- 自动故障转移
- 自动恢复
4、mongodb中副本集的设置:
(1)关闭正在运行的mongodb服务器
(2)通过指定 --replSet 选项来启动mongoDB。--replSet 基本语法格式如下:
mongod --port "PORT" --dbpath "YOUR_DB_DATA_PATH" --replSet "REPLCA_SET_INSTANCE_NAME"
参数说明:
PORT --服务器端口
YOUR_DB_DATA_PATH --服务器地址URL
REPLCA_SET_INSTANCE_NAME --实例名
实例:
mongod --port 27017 --dbpath "D:\set up\mongodb\data" --replSet rs0
以上实例会启动一个名为rs0的mongodb实例,端口号为27017。
启动后会打开命令提示框并连接服务。
(3)在Mongo客户端使用命令 rs.initiate() 启动一个新的副本集。
(4)使用rs.conf() 来查看副本集配置。
(5)使用rs.status() 来查看副本集状态。
5、副本集添加成员