MongoDB——基础操作
Posted 小王子jvm
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MongoDB——基础操作相关的知识,希望对你有一定的参考价值。
MongoDB基本介绍
传统的关系型数据库(如mysql),在数据操作的“三高”需求以及应对Web2.0的网站需求面前,显得力不从心。 解释:“三高”需求:
- High performance - 对数据库高并发读写的需求。
- Huge Storage - 对海量数据的高效率存储和访问的需求。
- High Scalability && High Availability- 对数据库的高可扩展性和高可用性的需求。
而MongoDB可应对“三高”需求。
具体的应用场景如:
- 社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。
- 游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、高效率存储和访问。
- 物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。
- 物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析。
- 视频直播,使用 MongoDB 存储用户信息、点赞互动信息等。
这些应用场景中,数据操作方面的共同特点是: 数据量大 、写入操作频繁(读写都很频繁)、价值较低的数据,对事务性要求不高对于这样的数据,我们更适合使用MongoDB来实现数据的存储。
所以什么是MongoDB?
MongoDB是一个开源、高性能、无模式的文档型数据库,当初的设计就是用于简化开发和方便扩展,是NoSQL数据库产品中的一种。是最 像关系型数据库(MySQL)的非关系型数据库。
它支持的数据结构非常松散,是一种类似于 JSON 的 格式叫BSON,所以它既可以存储比较复杂的数据类型,又相当的灵活。
MongoDB中的记录是一个文档,它是一个由字段和值对(field:value)组成的数据结构。MongoDB文档类似于JSON对象,即一个文档认为就是一个对象。字段的数据类型是字符型,它的值除了使用基本的一些类型外,还可以包括其他文档、普通数组和文档数组。
什么东西都是这样,类比一下,一下子就清晰了很多:
SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据行/文档 |
column | filed | 数据库字段/域 |
index | index | 索引 |
table joins | 表连接,MongoDB不支持 | |
嵌入文档 | MongoDB通过嵌入式文档来替代多表连接 | |
primary key | primary key | 主键/MongoDB自动将_id字段设置为主键 |
数据类型
MongoDB的最小存储单位就是文档(document)对象。文档(document)对象对应于关系型数据库的行。数据在MongoDB中以 BSON(Binary-JSON)文档的格式存储在磁盘上。
BSON(Binary Serialized Document Format)是一种类似json的一种二进制形式的存储格式,简称Binary JSON。BSON和JSON一样,支持内嵌的文档对象和数组对象,但是BSON有JSON没有的一些数据类型,如Date和BinData类型。
BSON采用了类似于 C 语言结构体的名称、对表示方法,支持内嵌的文档对象和数组对象,具有轻量性、可遍历性、高效性的三个特点,可以有效描述非结构化数据和结构化数据。这种格式的优点是灵活性高,但它的缺点是空间利用率不是很理想。
单机部署(安装流程)
Windows安装
下载安装包
MongoDB 提供了可用于 32 位和 64 位系统的预编译二进制包,你可以从MongoDB官网下载安装,MongoDB 预编译二进制包下载地址: https://www.mongodb.com/download-center#community
下载zip压缩包,然后解压到一个文件夹中,在解压目录中自己手动简历一个文件夹用来放数据:例如:data/db
启动方式:
- 在 bin 目录中打开命令行提示符,输入如下命令:
mongod --dbpath=..\\data\\db
在启动信息中可以看到,mongoDB的默认端口是27017,如果我们想改变默认的启动端口,可以通过–port来指定端口。 为了方便我们每次启动,可以将安装目录的bin目录设置到环境变量的path中, bin 目录下是一些常用命令,比如 mongod 启动服务用的, mongo 客户端连接服务用的。
- 配置文件方式启动服务
在解压目录中新建 config 文件夹,该文件夹中新建配置文件 mongod.conf ,内如参考如下:
storage:
#指定数据文件位置,也就是上面创建的文件夹
dbPath: D:\\学习资源\\mongodb\\mongodb-win32-x86_64-windows-4.4.6\\data\\db
详细配置项内容可以参考官方文档:https://docs.mongodb.com/manual/reference/configuration-options/
[ PS ]:配置文件中如果使用双引号,比如路径地址,自动会将双引号的内容转义。如果不转义,则会报错:
启动方式:mongod -f ../config/mongod.conf
或 mongod --config ../config/mongod.conf
其他配置参考:
systemLog:
destination: file
#生成的日志文件放在那个位置
path: "D:/mongodb-win32-x86_64-2008plus-ssl-4.0.1/log/mongod.log"
#产生的日志以追加的方式添加
logAppend: true
storage:
journal:
enabled: true
#数据文件
dbPath: "D:/mongodb-win32-x86_64-2008plus-ssl-4.0.1/data"
net:
#bindIp: 127.0.0.1
port: 27017
setParameter:
#
enableLocalhostAuthBypass: false
Shell连接(mongo命令)
在命令提示符输入以下shell命令即可完成登陆 mongo
或 mongo --host=127.0.0.1 --port=27017
查看已经有的数据库 : >show databases(其实这个数据库和MySQL有点像,只不过MySQL存储数据是拆散,这个是一个文档也就是完整的存储,然后二者的语法使用不同罢了)
退出:exit
Compass-图形化界面客户端
到MongoDB官网下载MongoDB Compass 地址:https://www.mongodb.com/try/download/compass
如果是下载安装版,则按照步骤安装;如果是下载加压缩版,直接解压,执行里面的 MongoDBCompassCommunity.exe
文件即可。 在打开的界面中,输入主机地址、端口等相关信息,点击连接:然后输入对应的IP和端口即可。
Linux系统安装
其实和Windows差不多也是这几个操作,步骤如下:(有点坑最好使用docker部署)
-
下载对应的安装包:mongod-linux-x86_64-4.0.10.tgz 。
-
上传压缩包到Linux中,解压到当前目录:
tar -xvf mongodb-linux-x86_64-4.0.10.tgz
-
移动解压后的文件夹到指定的目录中:
mv mongodb-linux-x86_64-4.0.10 /usr/local/mongodb
-
新建几个目录,分别用来存储数据和日志:
#数据存储目录 mkdir -p /mongodb/single/data/db #日志存储目录 mkdir -p /mongodb/single/log
-
新建并修改配置文件:
vi /mongodb/single/mongod.conf
配置文件的内容如下:
systemLog: #MongoDB发送所有日志输出的目标指定为文件 destination: file #mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径 path: "/mongodb/single/log/mongod.log" #当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。 logAppend: true storage: #mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod。 dbPath: "/mongodb/single/data/db" journal: #启用或禁用持久性日志以确保数据文件保持有效和可恢复。 enabled: true processManagement: #启用在后台运行mongos或mongod进程的守护进程模式。 fork: true net: #服务实例绑定的IP,默认是localhost bindIp: localhost,192.168.0.2 #绑定的端口,默认是27017 port: 27017
注意格式是yaml格式!!!
-
启动MongoDB服务:
/usr/local/mongodb/bin/mongod -f /mongodb/single/mongod.conf
如果出错了,自行百度吧,不多不说21世纪了,用docker还是最舒服的。
docker安装方式
首先拉去镜像:docker pull mongo
然后启动容器运行这个镜像:docker run --name mongodb -p 27017:27017 -d mongo:latest
上面两种安装方式,如果有数据损坏,则需要进行如下操作(了解):
- 删除lock文件:
rm -f /mongodb/single/data/db/*.lock
- 修复数据:
./mongod --repair --dbpath=/mongodb/single/data/db
常用命令大全
基本案例
存放文章评论的数据存放到MongoDB中,数据结构参考如下:
数据库:articledb
数据库相关操作
-
选择和创建数据库:
use DBName
,如果这个数据库不存在会自动的创建。所以创建也是这个命令。 -
查看有权限查看的数据库:
show dbs
或者show databases
-
查看当前使用的数据库:
db
MongoDB 中默认的数据库为 test,如果你没有选择数据库,集合将存放在 test 数据库中。
-
删除数据库:
db.dropDatabase()
,主要用来删除已经持久化的数据库
有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。
- admin:保存的就是用户的基本信息以及对应的一个权限
- local: 用来存储限于本地单台服务器的任意集合
- config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。
集合相关操作
集合,类似关系型数据库中的表。 可以显示的创建,也可以隐式的创建
-
集合的创建
db.createCollection(name)
,这个name就是创建的集合名字。例如:创建一个sheep,db.createCollection(“sheep”).
-
查看当前数据库的集合:
show collections
或者show tables
(好家伙,直接和MySQL一样) -
集合的删除:
db.collection.drop()
【删除所有集合】 或者db.集合名字.drop()
【删除指定集合】如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。
例如删除上面创建的这个集合:
db.mycollection.drop()
当向一个集合中插入一个文档的时候,如果集合不存在,则会自动创建集合。
文档操作(CRUD)
文档(document)的数据结构和 JSON 基本一样。 所有存储在集合中的数据都是 BSON 格式
文档插入
- 单个插入,使用insert() 或 save() 方法向集合中插入文档,语法如下:
db.collection.insert(
json数据格式即可
)
# 例如:
db.comment.insert(
"articleid":"100000",
"content":"今天天气真好,阳光明媚",
"userid":"1001",
"nickname":"Rose",
"createdatetime":new Date(),
"likenum":NumberInt(10),
"state":null
)
# 说明:
1)comment集合如果不存在,则会隐式创建
2)mongo中的数字,默认情况下是double类型,如果要存整型,必须使用函数NumberInt(整型数字),否则取出来就有问题了。
3)插入当前日期使用 new Date()
4)插入的数据没有指定 _id ,会自动生成主键值
5)如果某字段没值,可以赋值为null,或不写该字段。
如果执行之后返回:WriteResult( "nInserted" : 1 )
代表插入成功。
- 文档中的键/值对是有序的。
- 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
- MongoDB区分类型和大小写。
- MongoDB的文档不能有重复的键。
- 文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。
文档键命名规范:
- 键不能含有\\0 (空字符)。这个字符用来表示键的结尾。
- .和$有特别的意义,只有在特定环境下才能使用。
- 以下划线"_"开头的键是保留的(不是严格要求的)。
- 批量插入,没什么好说的,就是多个json数据而已
db.comment.insert(
"_id":"1",
"articleid":"100000",
"content":"今天天气真好,阳光明媚",
"userid":"1001",
"nickname":"Rose",
"createdatetime":new Date(),
"likenum":NumberInt(10),
"state":null
,
"_id":"2",
"articleid":"100001",
"content":"今天天气真好,阳光明媚",
"userid":"1002",
"nickname":"Lisi",
"createdatetime":new Date(),
"likenum":NumberInt(32),
"state":null
)
插入时指定了 _id ,则主键就是该值。 如果某条数据插入失败,将会终止插入,但已经插入成功的数据不会回滚掉。 因为批量插入由于数据较多容易出现失败,因此,可以使用try catch进行异常捕捉处理,测试的时候可以不处理。如(了解):
try
db.comment.insertMany(
[
"_id":"1",
"articleid":"100000",
"content":"今天天气真好,阳光明媚",
"userid":"1001",
"nickname":"Rose",
"createdatetime":new Date(),
"likenum":NumberInt(10),
"state":null
,
"_id":"2",
"articleid":"100001",
"content":"今天天气真好,阳光明媚",
"userid":"1002",
"nickname":"Lisi",
"createdatetime":new Date(),
"likenum":NumberInt(32),
"state":null
]
)
catch(e)
print(e)
查询数据的语法格式如下:
db.collection.find(<query>, [projection])
-
query:可选。使用查询运算符指定选择筛选器。若要返回集合中的所有文档,请省略此参数或传递空文档 ( )。
-
projection : 可选。指定要在与查询筛选器匹配的文档中返回的字段(投影)。若要返回匹配文档中的所有字段, 请省略此参数。
比如查询所有:db.comment.find()
或 db.comment.find()
这里你会发现每条文档会有一个叫_id的字段,这个相当于我们原来关系数据库中表的主键,当你在插入文档记录时没有指定该字段,MongoDB会自动创建,其类型是ObjectID类型。 如果我们在插入文档记录时指定该字段也可以,其类型可以是ObjectID类型,也可以是MongoDB支持的任意类型。
- 按一定条件来查询
比如我想查询userid为1003的记录,怎么办?很简单!只 要在find()中添加参数即可,参数也是json格式,如:db.comment.find(userid:'1003')
如果你只需要返回符合条件的第一条数据,我们可以使用findOne命令来实现,语法和find一样。 如:查询用户编号是1003的记录,但只最多返回符合条件的第一条记录:db.comment.findOne(userid:'1003')
- 投影查询(Projection Query):
如果要查询结果返回部分字段,则需要使用投影查询(不显示所有字段,只显示指定的字段)。
如:查询结果只显示 _id、userid、nickname :(1表示显示,0表示不显示)
> db.comment.find(userid:"1003",userid:1,nickname:1)
"_id" : "4", "userid" : "1003", "nickname" : "凯撒"
"_id" : "5", "userid" : "1003", "nickname" : "凯撒"
默认 _id 会显示。如:查询结果只显示 、userid、nickname ,不显示 _id :
> db.comment.find(userid:"1003",userid:1,nickname:1,_id:0)
"userid" : "1003", "nickname" : "凯撒"
"userid" : "1003", "nickname" : "凯撒"
文档的更新
更新文档的语法:
db.collection.update(query, update, options)
//或
db.collection.update(
<query>, //查找想更新的数据
<update>, //更新后的数据
//下面这都是可选项,代表一些更新的特性
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
hint: <document|string> // Available starting in MongoDB 4.2
)
例如:我们想修改_id为1的记录,点赞量为1001,输入以下语句:
db.comment.update(_id:"1",likenum:NumberInt(1001))
执行后,我们会发现,这条文档除了likenum字段其它字段都不见了,由于没有指定其他字段,默认删除了。
如果想要局部修改,们需要使用修改器$set来实现,命令如下:(修改_id为2的记录,浏览量为889)
db.comment.update(_id:"2",$set:likenum:NumberInt(889))
批量修改:
//默认只修改第一条数据
db.comment.update(userid:"1003",$set:nickname:"凯撒2")
//修改所有符合条件的数据,如果不加后面的参数,则只更新符合条件的第一条记录
db.comment.update(userid:"1003",$set:nickname:"凯撒大帝",multi:true)
列值增长的修改,实现对某列值在原有值的基础上进行增加或减少,可以使用 $inc 运算符来实现。
//对3号数据的点赞数,每次递增1
db.comment.update(_id:"3",$inc:likenum:NumberInt(1))
文档删除
删除文档的语法结构:db.集合名称.remove(条件)
以下语句可以将数据全部删除,请慎用:db.集合名称.remove()
如果删除指定条件的例如:db.comment.remove(_id;"1")
高级的查询
统计查询
统计查询使用count()方法,语法如下:db.collection.count(query, options)
例如:统计所有记录数量:db.comment.count()
再如:按条件统计记录数(统计userid为1003的记录条数):db.comment.count(userid:"1003")
默认情况下 count() 方法返回符合条件的全部记录条数
分页查询
可以使用limit()方法来读取指定数量的数据,使用skip()方法来跳过指定数量的数据。
基本语法如下所示:db.collection.find().limit(NUMBER).skip(NUMBER)
如果你想返回指定条数的记录,可以在find方法后调用limit来返回结果(TopN),默认值20,例如:db.comment.find().limit(3)
skip方法同样接受一个数字参数作为跳过的记录条数。(前N个不要),默认值是0
db.comment.find().skip(3)
需求:每页2个,第二页开始:跳过前两条数据,接着值显示3和4条数据
//第一页
db.comment.find().skip(0).limit(2)
//第二页
db.comment.find().skip(2).limit(2)
//第三页
db.comment.find().skip(4).limit(2)
总的来说跟MySQL使用差不多,用法不同罢了。
排序查询
sort() 方法对数据进行排序,sort() 方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用 于降序排列。
语法如下所示:db.集合名称.find().sort(排序方式)
例如:对userid降序排列,并对访问量进行升序排列:db.comment.find().sort(userid:-1,likenum:1)
skip(), limilt(), sort()
三个放在一起执行的时候,执行的顺序是先 sort(), 然后是 skip(),最后是显示的 limit(),和命令编写顺序无关。
正则表达式条件查询
MongoDB的模糊查询是通过正则表达式的方式实现的。格式为:
db.集合.find(字段:/正则表达式/)
正则表达式是js的语法,直接量的写法。 例如,我要查询评论内容包含“开水”的所有文档,代码如下:db.comment.find(content:/开水/)
如果要查询评论的内容中以“专家”开头的,代码如下:db.comment.find(content:/^专家/)
比较查询
<, <=, >, >= 这个操作符也是很常用的,格式如下:
db.集合名称.find( "field" : $gt: value ) // 大于: field > value
db.集合名称.find( "field" : $lt: value ) // 小于: field < value
db.集合名称.find( "field" : $gte: value ) // 大于等于: field >= value
db.集合名称.find( "field" : $lte: value ) // 小于等于: field <= value
db.集合名称.find( "field" : $ne: value ) // 不等于: field != value
查询评论点赞数量大于700的记录:db.comment.find(likenum:$gt:NumberInt(700))
包含查询
包含使用$in操作符。 示例:查询评论的集合中userid字段包含1003或1004的文档
db.comment.find(userid:$in:["1003","1004"])
不包含使用$nin操作符。 示例:查询评论集合中userid字段不包含1003和1004的文档:
db.comment.find(userid:$nin:["1003","1004"])
条件连接查询
我们如果需要查询同时满足两个以上条件,需要使用$and操作符将条件进行关联。(相 当于SQL的and) 格式为:$and:[ , , ]
示例:查询评论集合中likenum大于等于700 并且小于2000的文档
db.comment.find($and:[likenum:$gte:NumberInt(700),likenum:$lt:NumberInt(2000)])
如果两个以上条件之间是或者的关系,我们使用 操作符进行关联,与前面 and的使用方式相同格式为:$or:[ , , ]
查询评论集合中userid为1003,或者点赞数小于1000的文档记录:
db.comment.find($or:[ userid:"1003" ,likenum:$lt:1000 ])
常用命令小结
选择切换数据库:use articledb
插入数据:db.comment.insert(bson数据)
查询所有数据:db.comment.find();
条件查询数据:db.comment.find(条件)
查询符合条件的第一条记录:db.comment.findOne(条件)
查询符合条件的前几条记录:db.comment.find(条件).limit(条数)
查询符合条件的跳过的记录:db.comment.find(条件).skip(条数)
修改数据:db.comment.update(条件,修改后的数据) 或db.comment.update(条件,$set:要修改部分的字段:数据)
修改数据并自增某字段值:db.comment.update(条件,$inc:自增的字段:步进值)
删除数据:db.comment.remove(条件)
统计查询:db.comment.count(条件)
模糊查询:db.comment.find(字段名:/正则表达式/)
条件比较运算:db.comment.find(字段名:$gt:值)
包含查询:db.comment.find(字段名:$in:[值1,值2])或db.comment.find(字段名:$nin:[值1,值2])
条件连接查询:db.comment.find($and:[条件1,条件2])或db.comment.find($orMongoDB基础命令及操作
MongoDB基础教程系列--第二篇 MongoDB基本操作
Mongodb基础操作实践- -Mongodb Shell端