1.MongoDB简介
MongoDB是一个开源的,基于分布式的,面向文档存储的非关系型
数据库,是非关系型数据库中比较像关系型数据库的。MongoDB由C++编写,名字来源于humongous
这个单词,旨在于处理大量数据。
MongoDB 将数据存储为一个文档,数据结构由键值(key-value)对组成。MongoDB 文档类似于JSON
对象。字段值可以包含其他文档,数组及文档数组。
MongoDB的特点:
- 面向集合存储,易存储对象类型的数据。
- 模式自由。集合中没有行和列的概念,每个文档可以有不同的key,key的值不要求一致的数据类型。
- 支持动态查询。支持丰富的查询表达式,查询指令可以使用JSON形式表达式。
- 支持索引。
- 支持查询。
- 支持复制和故障恢复。
- 使用高效的二进制数据存储,包括大型对象(如视频等)。
- 自动处理碎片,以支持云计算层次的扩展性。
- 支持C/C++,PHP,Ruby,Python,Java等多种语言。
- 文件存储格式为
BSON
(一种JSON的扩展,JSON的二进制)
MongoDB应用场景:
- 京东,中国著名电商,使用MongoDB存储商品信息,支持比价和关注功能。
- 赶集网,中国著名分类信息网站,使用MongoDB记录pv浏览计数。
- 奇虎360,著名病毒软件防护和移动应用平台,使用MongoDB支撑的HULK平台每天接受200亿次的查询。
- 百度云,使用MongoDB管理百度云盘中500亿条关于文件源信息的记录。
2.MongoDB的基本概念
在mongodb中基本的概念是文档、集合、数据库。
SQL术语 | MongoDB术语 | 说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表、集合 |
row | document | 数据记录行、文档 |
column | field | 数据字段、域 |
index | index | 索引 |
table joins | 嵌入文档 | 表连接,MongoDB不支持,可通过内嵌和包含关联ID实现 |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
- 文档
文档是一个键值(key-value)对(即BSON)。MongoDB的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是 MongoDB 非常突出的特点。 - 集合
文档组,类似于关系数据库中的表格。集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。当第一个文档插入时,集合就会被创建。
比如,我们可以将以下不同数据结构的文档插入到集合中:
{"site":"www.baidu.com"}
{"site":"www.google.com","name":"Google"}
- 分布式数据库系统
由分布于多个计算机结点上的若干个数据库系统组成,它提供有效的存取手段来操纵这些结点上的子数据库。分布式数据库在使用上可视为一个完整的数据库,而实际上它是分布在地理分散的各个结点上。 ObjectId
数据类型
ObjectId
类似唯一主键,可以很快的去生成和排序,包含12 bytes
。
3.MongoDB的基本操作
3.1 创建删除数据库
创建/切换:
use DATABASE_NAME
显示所有数据库名:
show dbs
查看当前数据库的名称:
db
查看所有的collection,下面两条指令都可以:
show collections
show tables
删除当前的数据库
db.dropDatabase()
MongoDB 中默认的数据库为 test,如果你没有创建新的数据库,集合将存放在 test 数据库中。
3.2 增加文档
MongoDB 使用 insert() 或 save() 方法向集合中插入文档:
db.COLLECTION_NAME.insert(document)
例如:
db.test.insert({title: 'mongo test',
description: 'MongoDB是Nosql数据库',
url: 'http://mongodb.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 200
})
> db.test.insert({title: 'mongo test',
... description: 'MongoDB是Nosql数据库',
... url: 'http://mongodb.com',
... tags: ['mongodb', 'database', 'NoSQL'],
... likes: 200
... })
WriteResult({ "nInserted" : 1 })
> db.test.find()
{ "_id" : ObjectId("5e393d940cd9aa50e890348c"), "title" : "mongo test", "description" : "MongoDB是Nosql数据库", "url" : "http://mongodb.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 200 }
insert() 和 save() 方法区别:
- save函数实际就是根据参数条件,调用了insert或update函数。如果想插入的数据对象存在,insert函数会报错,而save函数是改变原来的对象。如果想插入的对象不存在,那么它们执行相同的插入操作。
- insert可以一次性插入一个列表,而不用遍历,效率高, save则需要遍历列表,一个个插入。
- 如果不指定
_id
字段save()
方法类似于insert()
方法。如果指定_id
字段,则会更新该_id
的数据。
3.2版本后还有以下几种语法可用于插入文档:
db.collection.insertOne()
:向指定集合中插入一条文档数据db.collection.insertMany()
:向指定集合中插入多条文档数据
> var document = db.test.insertOne({"a": 3})
> document
{
"acknowledged" : true,
"insertedId" : ObjectId("5e393e640cd9aa50e890348d")
}
> db.test.find()
{ "_id" : ObjectId("5e393d940cd9aa50e890348c"), "title" : "mongo test", "description" : "MongoDB是Nosql数据库", "url" : "http://mongodb.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 200 }
{ "_id" : ObjectId("5e393e640cd9aa50e890348d"), "a" : 3 }
> var res = db.test.insertMany([{"b": 3}, {'c': 4}])
> res
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5e393e980cd9aa50e890348e"),
ObjectId("5e393e980cd9aa50e890348f")
]
}
> db.test.find()
{ "_id" : ObjectId("5e393d940cd9aa50e890348c"), "title" : "mongo test", "description" : "MongoDB是Nosql数据库", "url" : "http://mongodb.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 200 }
{ "_id" : ObjectId("5e393e640cd9aa50e890348d"), "a" : 3 }
{ "_id" : ObjectId("5e393e980cd9aa50e890348e"), "b" : 3 }
{ "_id" : ObjectId("5e393e980cd9aa50e890348f"), "c" : 4 }
>
3.3 查询文档
查询格式如下:
db.COLLECTION_NAME.find({COND},{FIELDS})
find() 方法以非结构化的方式来显示所有文档。
如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:
db.test.find().pretty()
> db.test.find().pretty()
{
"_id" : ObjectId("5e393d940cd9aa50e890348c"),
"title" : "mongo test",
"description" : "MongoDB是Nosql数据库",
"url" : "http://mongodb.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" : 200
}
{ "_id" : ObjectId("5e393e640cd9aa50e890348d"), "a" : 3 }
{ "_id" : ObjectId("5e393e980cd9aa50e890348e"), "b" : 3 }
{ "_id" : ObjectId("5e393e980cd9aa50e890348f"), "c" : 4 }
3.4 修改文档
更新数据格式如下:
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
参数说明:
- query:update的查询条件,类似sql update查询内where后面的。
- update:update的对象和一些更新的操作符(如 , , ,inc…)等,也可以理解为sql update查询内set后面的
- upsert :可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
- multi :可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true, 就把按条件查出来多条记录全部更新。
- writeConcern :可选,抛出异常的级别。
实例:
我们在集合col
中插入如下数据:
> db.col.insert({
... title: 'MongoDB 教程',
... description: 'MongoDB 是一个 Nosql 数据库',
... url: 'http://www.baidu.com',
... tags: ['mongodb', 'database', 'NoSQL'],
... likes: 100
... })
WriteResult({ "nInserted" : 1 })
接着我们通过 update()
方法来更新标题(title
):
> db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) # 输出信息
可以看到标题(title
)由原来的 "MongoDB 教程"
更新为了 "MongoDB"
。以上语句只会修改第一条发现的文档,如果你要修改多条相同的文档,则需要设置 multi
参数为 true
。
> db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}},{multi:true})
3.5 删除文档
执行remove()函数前先执行find()命令来判断执行的条件是否正确
db.collection.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
参数说明:
- query :(可选)删除的文档的条件。
- justOne : (可选)如果设为 true 或 1,则只删除一个文档.默认是true
- writeConcern :(可选)抛出异常的级别。
例如:
> db.col.find()
{ "_id" : ObjectId("5e396c6b0cd9aa50e8903491"), "title" : "MongoDB", "description" : "MongoDB 是一个 Nosql 数据库", "url" : "http://www.baidu.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
> db.col.remove({ "_id" : ObjectId("5e396c6b0cd9aa50e8903491")})
WriteResult({ "nRemoved" : 1 })