一、概述
MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
MongoDB 更类似 MySQL,支持字段索引、where等查询,其优势在于查询功能比较强大,擅长查询 JSON 数据,且能存储海量数据,但是不支持事务。
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,支持多种类型的数据结构,可用作数据库,高速缓存和消息队列代理。
4、性能
Mongodb依赖内存,TPS较高;
Redis依赖内存,TPS非常高。性能上Redis优于MongoDB。
5、可靠性
mongodb从1.8版本后,采用binlog方式(与MySQL采用同样方式)支持持久化,增加可靠性;
Redis依赖快照进行持久化;AOF增强可靠性;增强可靠性的同时,影响访问性能。
可靠性上MongoDB优于Redis。
6、数据分析
mongodb内置数据分析功能(mapreduce);而Redis不支持。
7、事务支持情况
Redis 事务支持比较弱,只能保证事务中的每个操作连续执行;mongodb不支持事务。
8、集群
MongoDB 集群技术比较成熟,Redis从3.0开始支持集群。
(1)文档
文档是 MongoDB 中数据的基本单位,文档类似于关系数据库中的行(但是比行复杂)。多个键及其关联的值有序地放在一起就构成了文档。不同的编程语言对文档的表示方法不同,在JavaScript 中文档表示为:
{“greeting”:“hello,world”}
这个文档只有一个键“greeting”,对应的值为“hello,world”。多数情况下,文档比这个更复杂,它包含多个键/值对。例如:
{“greeting”:“hello,world”,“foo”: 3}
文档中的键/值对是有序的,下面的文档与上面的文档是完全不同的两个文档。
{“foo”: 3 ,“greeting”:“hello,world”}
文档中的值不仅可以是双引号中的字符串,也可以是其他的数据类型,例如,整型、布尔型等,也可以是另外一个文档,即文档可以嵌套。文档中的键类型只能是字符串。
2)集合
集合就是一组文档,类似于关系数据库中的表。集合是无模式的,集合中的文档可以是各式各样的。例如,{“hello,word”:“Mike”}和{“foo”: 3},它们的键不同,值的类型也不同,但是它们可以存放在同一个集合中,也就是不同模式的文档都可以放在同一个集合中。既然集合中可以存放任何类型的文档,那么为什么还需要使用多个集合?这是因为所有文档都放在同一个集合中,无论对于开发者还是管理员,都很难对集合进行管理,而且这种情形下,对集合的查询等操作效率都不高。所以在实际使用中,往往将文档分类存放在不同的集合中,例如,对于网站的日志记录,可以根据日志的级别进行存储,Info级别日志存放在Info 集合中,Debug 级别日志存放在Debug 集合中,这样既方便了管理,也提供了查询性能。但是需要注意的是,这种对文档进行划分来分别存储并不是MongoDB 的强制要求,用户可以灵活选择。
可以使用“.”按照命名空间将集合划分为子集合。例如,对于一个博客系统,可能包括blog.user 和blog.article 两个子集合,这样划分只是让组织结构更好一些,blog 集合和blog.user、blog.article 没有任何关系。虽然子集合没有任何特殊的地方,但是使用子集合组织数据结构清晰,这也是MongoDB 推荐的方法。
(3)数据库
MongoDB 中多个文档组成集合,多个集合组成数据库。一个MongoDB 实例可以承载多个数据库。它们之间可以看作相互独立,每个数据库都有独立的权限控制。在磁盘上,不同的数据库存放在不同的文件中。MongoDB 中存在以下系统数据库。
● Admin 数据库:一个权限数据库,如果创建用户的时候将该用户添加到admin 数据库中,那么该用户就自动继承了所有数据库的权限。
● Local 数据库:这个数据库永远不会被复制,可以用来存储本地单台服务器的任意集合。
● Config 数据库:当MongoDB 使用分片模式时,config 数据库在内部使用,用于保存分片的信息。
一个MongoDB 实例可以包含一组数据库,一个数据库可以包含一组Collection(集合),一个集合可以包含一组Document(文档)。一个Document包含一组field(字段),每一个字段都是一个key/value pair。
key: 必须为字符串类型。
value:可以包含如下类型。
● 基本类型,例如,string,int,float,timestamp,binary 等类型。
● 一个document。
● 数组类型。
MongoDB 的主要目标是在键/值存储方式(提供了高性能和高度伸缩性)和传统的RDBMS 系统(具有丰富的功能)之间架起一座桥梁,它集两者的优势于一身。根据官方网站的描述,Mongo 适用于以下场景。
● 网站数据:Mongo 非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
● 缓存:由于性能很高,Mongo 也适合作为信息基础设施的缓存层。在系统重启之后,由Mongo 搭建的持久化缓存层可以避免下层的数据源过载。
● 大尺寸、低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储。
● 高伸缩性的场景:Mongo 非常适合由数十或数百台服务器组成的数据库,Mongo 的路线图中已经包含对MapReduce 引擎的内置支持。
● 用于对象及JSON 数据的存储:Mongo 的BSON 数据格式非常适合文档化格式的存储及查询。
MongoDB 的使用也会有一些限制,例如,它不适合于以下几个地方。
● 高度事务性的系统:例如,银行或会计系统。传统的关系型数据库目前还是更适用于需要大量原子性复杂事务的应用程序。
● 传统的商业智能应用:针对特定问题的BI 数据库会产生高度优化的查询方式。对于此类应用,数据仓库可能是更合适的选择。
● 需要SQL 的问题。
linux中安装docker自行百度:
安装好了后:
#拉取镜像
docker pull mongo:latest
#创建和启动容器
docker run -d --restart=always -p 27017:27017 --name mymongo -v /data/db:/data/db -d mongo
启动并加入开机启动
systemctl start docker
systemctl enable docker
#进入容器
docker exec -it mymongo /bin/bash
#使用MongoDB客户端进行操作
mongo
然后:
show dbs #查询所有的数据库
admin 0.000GB
config 0.000GB
语法:use 数据库名字
use DATABASE_NAME
说明:有则切换,无则创建
如果数据库不存在,则创建数据库,否则切换到指定数据库。
db
show dbs
说明:当我们创建一个新的数据路的时候,使用show dbs ,发现新的数据库不显示出来,此时向新数据库插入数据才能显示
简单向数据库插入数据:db.数据库.insert({“key1”:“value1”})
db.mydb.insert({“key1”:“value1”})
成功标志:WriteResult({ “nInserted” : 1 })
语法:
db.dropDatabase()
说明:先使用db查看当前所在的数据库,然后再删除
db.dropDatabase()
{ “ok” : 1 }
show dbs # 查看是否删除
db.createCollection(“c1”) # 先创建集合,类似数据库中的表
db.createCollection(“c1”)
成功标志:{ “ok” : 1 }
show tables # show collections 命令会更加准确点
show collections
db.collection.drop()
如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。
案例:
> use demo # 使用demo数据库
switched to db demo
> show tables # 查看当前数据库所有集合
demo
info
myclo2
mycol
> db.demo.drop() # 删除demo集合
true
> show tables;
info
myclo2
mycol
>
db.集合名字.find()
文档的数据结构和 JSON 基本一样。所有存储在集合中的数据都是 BSON 格式。BSON 是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON 的简称。
语法
MongoDB 使用 insert() 或 save() 方法向集合中插入文档,语法如下:
db.集合名字.insert(document)
或
db.集合名字.save(document)
案例:
db.集合名字.insert({“a”: 3,“name”:“tom”}) #一个{}中的是一行数据
WriteResult({ “nInserted” : 1 })
插入方法说明:
save():如果 _id 主键存在则更新数据,如果不存在就插入数据。该方法新版本中已废弃,可以使用 db.collection.insertOne() 或 db.collection.replaceOne() 来代替。
insert(): 若插入的数据主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常,提示主键重复,不保存当前数据
3.2 版本之后新增了 db.collection.insertOne() 和 db.collection.insertMany()。
连接到MongoDB,使用命令查看MongoDB版本:db.version()
db.集合名字.insertOne():
db.集合名字.insertOne({“b”: 2})
案例:db.mydb.insertOne({“b”:2})
{
“acknowledged” : true,
“insertedId” : ObjectId(“62eb9f45d54305f4ebf468d4”)
}
db.collection.insertMany() 用于向集合插入一个多个文档,语法格式如下:
db.collection.insertMany([{"b": 3}, {'c': 4}])
> res
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5ed5a93f56fa4269b4e25600"),
ObjectId("5ed5a93f56fa4269b4e25601")
]
}
插入文档你也可以使用 db.集合名字.save(document)命令。如果不指定 _id 字段 save() 方法类似于 insert() 方法。如果指定 _id 字段,则会更新该 _id 的数据。
案例:
> db.集合名字.save({"222":234})
WriteResult({ "nInserted" : 1 })
MongoDB 使用 update() 和 save() 方法来更新集合中的文档。接下来让我们详细来看下两个函数的应用及其区别。
update() 方法:
语法
update() 方法用于更新已存在的文档。语法格式如下:
db.collection.update(
,
,
{
upsert: ,
multi: ,
writeConcern:
}
)
参数解释:
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 数据库',
by: '菜鸟教程',
url: 'http://www.runoob.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 })
> db.col.find().pretty()
{
"_id" : ObjectId("5ed5a7e356fa4269b4e255fd"),
"title" : "MongoDB",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "菜鸟教程",
"url" : "http://www.runoob.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" : 100
}
可以看到标题(title)由原来的 “MongoDB 教程” 更新为了 “MongoDB”。
注意:以上语句只会修改第一条发现的文档,如果你要修改多条相同的文档,则需要设置 multi 参数为 true。
save() 方法:
save() 方法:
save() 方法通过传入的文档来替换已有文档,_id 主键存在就更新,不存在就插入。
语法:
db.collection.save(
,
{
writeConcern:
}
)
document : 文档数据。
writeConcern :可选,抛出异常的级别。
案例:
执行更新:id主键存在时候是更新:
db.集合名字.save({
"_id" : ObjectId("5ed5a7e356fa4269b4e255fd"),
"title" : "MongoDB_Zysheep",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "Zysheep",
"url" : "http://www.zysheep.cn",
"tags" : [
"mongodb",
"NoSQL",
"zysheep"
],
"likes" : 120
})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
MongoDB remove()函数是用来移除集合中的数据。MongoDB数据更新可以使用update()函数。在执行remove()函数前先执行find()命令来判断执行的条件是否正确,这是一个比较好的习惯。
语法:
db.collection.remove(
,
)
query :(可选)删除的文档的条件。
justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
writeConcern :(可选)抛出异常的级别。
案例:
# 查询所有数据
> db.collection.find()
{ "_id" : ObjectId("5ed5a7e356fa4269b4e255fd"), "title" : "MongoDB_Zysheep", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "Zysheep", "url" : "http://www.zysheep.cn", "tags" : [ "mongodb", "NoSQL", "zysheep" ], "likes" : 120 }
{ "_id" : ObjectId("5ed5a81856fa4269b4e255fe"), "title" : "MongoDB", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
{ "_id" : ObjectId("5ed5aa2156fa4269b4e25602"), "title" : "MongoDB", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
# 移除 title 为 'MongoDB' 的文档
>db.collection.remove({'title':'MongoDB'})
WriteResult({ "nRemoved" : 2 })
# 再次查询所有文档
>db.collection.find()
如果你只想删除第一条找到的记录可以设置 justOne 为 1
db.COLLECTION_NAME.remove(DELETION_CRITERIA,1)
注意
remove() 方法已经过时了,现在官方推荐使用deleteOne()和 deleteMany() 方法。
如删除集合下全部文档:
db.COLLECTION_NAME.deleteMany({})
删除 status 等于 A 的全部文档:
db.COLLECTION_NAME.deleteMany({ status : “A” })
删除 status 等于 D 的一个文档:
db.COLLECTION_NAME.deleteOne( { status: “D” } )
11.MongoDB 查询文档:
MongoDB 查询文档使用 find() 方法。
语法:
db.collection.find(query, projection)
参数说明:
query :可选,使用查询操作符指定查询条件
projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:
db.集合名字.find().pretty()
案例:
>db.mydb.find()
{ "_id" : ObjectId("62eb9990d83569d555d482ba"), "key1" : "value1" }
{ "_id" : ObjectId("62eb9eb98282165b28efdf03"), "a" : 1 }
{ "_id" : ObjectId("62eb9f45d54305f4ebf468d4"), "b" : 2 }
{ "_id" : ObjectId("62eba340d54305f4ebf468d5"), "222" : 234 }
> db.mydb.find().pretty()
{ "_id" : ObjectId("62eb9990d83569d555d482ba"), "key1" : "value1" }
{ "_id" : ObjectId("62eb9eb98282165b28efdf03"), "a" : 1 }
{ "_id" : ObjectId("62eb9f45d54305f4ebf468d4"), "b" : 2 }
{ "_id" : ObjectId("62eba340d54305f4ebf468d5"), "222" : 234 }