linux环境下MongoDB的部署及应用
本文引自https://www.cnblogs.com/kevingrace/p/5752382.html大神的博客
一、Mongodb简介
MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能
最丰富,最像关系数据库的。它在许多场景下可用于替代传统的关系型数据库或键/值存储方式。它是由C++语言编写的一个基于分布式文件存储的开源数据库系统,它的目的在于为WEB应
用提供可扩展的高性能数据存储解决方案。MongoDB是一个介于关系型数据库和非关系型数据库之间的产品,是非关系型数据库当中功能最丰富,最像关系型数据库的。它支持的数据结构
非常松散,会将数据存储为一个文档,数据结构由键值对(key=>value)组成,是类似于json的bson格式,字段值可以包含其它文档、数组和文档数组,因此可以存储比较复杂的数据类型。
二、Mongodb特点
MongoDB特点是高性能、易部署、易使用,存储数据非常方便,最大的特点在于它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系型数据库单表
查询的绝大部分功能,而且还支持对数据建立索引。MongoDB的主要特点总结如下:
1)提供了一个面向集合的文档存储,易存储对象类型的数据,操作起来比较简单和容易的非关系型数据库
2)使用update()命令可以实现替换完成的文档(数据)或者一些指定的数据字段。
3)支持动态查询。
4)支持完全索引,包含内部对象,可以在MongoDB记录中设置任何属性的索引来实现更快的排序。
5)支持复制和故障恢复。
6)使用高效的二进制数据存储,包括大型对象(如视频等)。
7)GridFS是MongoDB中的一个内置功能,可以用于存放大量小文件。
8)自动处理碎片,以支持云计算层次的扩展性;如果负载的增加(需要更多的存储空间和更强的处理能力),它可以分布在计算机网络中的其它节点上,这就是所谓的分片。
9)支持RUBY,PYTHON,JAVA,C++,PHP,C
#等多种语言。
10)文件存储格式为BSON(一种JSON的扩展),MongoDB支持丰富的查询表达式,查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象和数组。
11)MongoDB允许在服务端执行脚本,可以用JavaScript编写某个函数,直接在服务端执行,也可以吧函数的定义存储在服务端,下次直接调用即可。
12)可通过网络访问,可以通过本地u或者网络创建数据镜像,这使得MongoDB含有更强的扩展性。
三、Mongodb的不足之处
1)在集群分片中的数据分布不均匀
2)单机可靠性比较差
3)大数据量持续插入,写入性能有较大波动
4)不支持事务操作。所以事务要求严格的系统(如果银行系统)肯定不能用它。
5)磁盘空间占用比较大。空间占用大的原因如下:
1-> 空间的预分配:为避免形成过多的硬盘碎片,mongodb 每次空间不足时都会申请生成一大块的硬盘空 间,而且申请的量从 64M、128M、256M 那样的指数递增,直到2G为单个文件
的最大体积。随着数据量 的增加,你可以在其数据目录里看到这些整块生成容量不断递增的文件。
2-> 字段名所占用的空间:为了保持每个记录内的结构信息用于查询,mongodb 需要把每个字段的 key-value 都以 BSON 的形式存储,如果 value 域相对于 key 域并不大,比如
存放数值型的数据,则数据的 overhead 是最大的。一种减少空间占用的方法是把字段名尽量取短一些,这样占用 空间就小了,但这就要求在易读 性与空间占用上作为权衡了。
3-> 删除记录不释放空间:这很容易理解,为避免记录删除后的数据的大规模挪动,原记录空间不删除,只 标记“已删除”即可,以后还可以重复利用。
4-> 可以定期运行 db.repairDatabase()来整理记录,但这个过程会比较缓慢
四、Mongodb功能
适用场景:
网站实时数据处理。它非常适合实时的插入、更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性;缓存,由于性能很高,它适合作为信息基础设施的缓存层。在系统重启之后,
由它搭建的持久化缓存层可以避免下层的数据源过载。高伸缩性的场景。非常适合由数十或数百台服务器组成的数据库,它的路线图中已经包含对MapReduce引擎的内置支持。
不适用场景:
要求高度事务性的系统。传统的商业智能应用。复杂的跨文档(表)级联查询。
五、Mongodb安装使用
官网下载地址:http://www.mongodb.org/downloads
一般官网下载比较麻烦,我这里有一个下载好的。链接:https://pan.baidu.com/s/1Ag3oUtqS4Pp3MueeK7AA9Q
提取码:dfvv
1.安装mongodb
[root@test-no ~]# cd /usr/local/src/ [root@test-no src]# tar -zxvf mongodb-linux-x86_64-3.4.18.tgz [root@test-no src]# mv mongodb-linux-x86_64-3.4.18 /usr/local/mongodb [root@test-no src]# cd /usr/local/mongodb/ #Mongodb主目录 [root@test-no mongodb]# ll total 116 drwxr-xr-x 2 root root 243 Jun 10 11:28 bin -rw-r--r-- 1 root root 34520 Nov 3 2018 GNU-AGPL-3.0 -rw-r--r-- 1 root root 16726 Nov 3 2018 MPL-2 -rw-r--r-- 1 root root 2266 Nov 3 2018 README -rw-r--r-- 1 root root 55625 Nov 3 2018 THIRD-PARTY-NOTICES [root@test-no mongodb]# mkdir /usr/local/mongodb/data #Mongodb数据目录,可以存放在一个独立的大分区上
[root@test-no mongodb]# mkdir /usr/local/mongodb/log #Mongodb日志目录
2.启动Mongodb
使用mongod命令建立一个mongodb数据库链接,数据库的路径为
/usr/local/mongodb/data
,日志路径为
/usr/local/mongodb/log/mongo
.log
mongodb的启动程序放在后台执行,下面命令执行后,按ctrl+c
#mongodb可以通过指定配置文件启动,也可以通过启动参数启动,下面我就是通过启动参数启动的
[root@test-no ~]# nohup /usr/local/mongodb/bin/mongod --dbpath=/usr/local/mongodb/data/ --logpath=/usr/local/mongodb/log/mongo.log &
#Mongodb启动参数说明:
--dbpath 数据库路径(数据文件)
--logpath 日志文件路径
--master 指定为主机器
--slave 指定为从机器
--
source
指定主机器的IP地址
--pologSize 指定日志文件大小不超过64M.因为resync是非常操作量大且耗时,最好通过设置一个足够大的oplogSize来避免resync(默认的 oplog大小是空闲磁盘大小的5%)。
--logappend 日志文件末尾添加
--port 启用端口号
--fork 在后台运行
--only 指定只复制哪一个数据库
--slavedelay 指从复制检测的时间间隔
--auth 是否需要验证权限登录(用户名和密码)
#mongodb默认端口是27017
[root@test-no ~]# ps -ef |grep mongodb root 8139 6648 0 14:02 pts/0 00:00:00 /usr/local/mongodb/bin/mongod --dbpath=/usr/local/mongodb/data/ --logpath=/usr/local/mongodb/log/mongo.log root 8410 6648 0 14:03 pts/0 00:00:00 grep --color=auto mongodb [root@test-no ~]# netstat -tunlp |grep 8139 tcp 0 0 0.0.0.0:27017 0.0.0.0:* LISTEN 8139/mongod [root@test-no ~]# lsof -i:27017 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME mongod 8139 root 7u IPv4 49592382 0t0 TCP *:27017 (LISTEN)
3.设置mongodb的环境变量
[root@test-no ~]# vim /etc/profile 。。。。。。。 export PATH=$PATH:/usr/local/mongodb/bin/ [root@test-no ~]# source /etc/profile
4.启动方式优化
为了更方便的启动和关闭MongoDB,我们可以使用Shell写脚本,当然也可以加入到service中
更好的方式是采用配置文件,把MongoDB需要的参数写入配置文件,然后在脚本中引用;
[root@test-no ~]# cat /usr/local/mongodb/mongodb.conf #这个文件默认不存在,自己创建#代表端口号,如果不指定则默认为27017
port=27888 #MongoDB数据文件目录
dbpath=/usr/local/mongodb/data#MongoDB日志文件目录
logpath=/usr/local/mongodb/log/mongo.log#日志文件自动累加
logappend=true
编写启动脚本
[root@test-no ~]# cat /etc/init.d/mongodb #!/bin/bash # # mongod Start up the MongoDB server daemon # # source function library . /etc/rc.d/init.d/functions #定义命令 CMD=/usr/local/mongodb/bin/mongod #定义配置文件路径 INITFILE=/usr/local/mongodb/mongodb.conf start() { #&表示后台启动,也可以使用fork参数 $CMD -f $INITFILE & echo "MongoDB is running background..." } stop() { pkill mongod echo "MongoDB is stopped." } case "$1" in start) start ;; stop) stop ;; *) echo $"Usage: $0 {start|stop}" esac
[root@test-no ~]# chmod 755 /etc/init.d/mongodb #加入执行权限
[root@test-no ~]# /etc/init.d/mongodb status
Usage: /etc/init.d/mongodb {start|stop}
[root@test-no ~]# ps -ef |grep mongodb #查看现在mongodb进程是否存在,我们这里发现进程不存在
root 21938 21765 0 15:05 pts/0 00:00:00 grep --color=auto mongodb
[root@test-no ~]# /etc/init.d/mongodb start #通过脚本启动mongodb
Starting mongodb (via systemctl): [ OK ]
[root@test-no ~]# ps -ef |grep mongodb #查看是否启动成功
root 22288 1 2 15:06 ? 00:00:00 /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/mongodb.conf
root 22391 21765 0 15:07 pts/0 00:00:00 grep --color=auto mongodb
[root@test-no ~]# netstat -tunlp|grep 22288
tcp 0 0 0.0.0.0:27888 0.0.0.0:* LISTEN 22288/mongod
[root@test-no ~]# lsof -i:27888 #这里我么看出mongodb的配置文件生效了
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mongod 22288 root 7u IPv4 49652899 0t0 TCP *:27888 (LISTEN)
#我们这里看一下脚本里的关闭参数有没有作用
[root@test-no ~]# /etc/init.d/mongodb stop
Stopping mongodb (via systemctl): Terminated
[root@test-no ~]# ps -ef |grep mongodb #这里我们看出关闭参数生效了
root 23712 21765 0 15:13 pts/0 00:00:00 grep --color=auto mongodb
六、Mongodb的日常操作命令
1.登录和退出
mongo 命令直接加MongoDB服务器的IP地址就可以利用 Mongo 的默认端口号(27017)登陆 Mongo,然后便能够进行简单的命令行操作。至于退出,直接
exit
,然后回车就好了。
如果默认bind绑定的ip是127.0.0.1以及端口是27017,那么登陆可以直接用下面两种都可以:
[root@master-node ~]# mongo [root@master-node ~]# mongo 127.0.0.1:27017
如果是绑定了固定的ip地址,如bind_ip=182.48.115.236,那么连接mongodb命令是:
[root@master-node ~]# mongo 182.48.115.238:27017
如果是连接某个库,命令是
[root@master-node ~]# mongo ip:port/库名 -u用户名 -p密码
登陆mongodb数据库后,可以直接执行help命令进行帮助查看
。。。。。 > help db.help() help on db methods db.mycoll.help() help on collection methods sh.help() sharding helpers rs.help() replica set helpers help admin administrative help help connect connecting to a db help help keys key shortcuts help misc misc things to know help mr mapreduce show dbs show database names show collections show collections in current database show users show users in current database show profile show most recent system.profile entries with time >= 1ms show logs show the accessible logger names show log [name] prints out the last segment of log in memory, 'global' is default use <db_name> set current database db.foo.find() list objects in collection foo db.foo.find( { a : 1 } ) list objects in foo where a == 1 it result of the last line evaluated; use to further iterate DBQuery.shellBatchSize = x set default number of items to display on shell exit quit the mongo shell
从以上可以看出,登录后 mongo 会自动连上一个名为
test
的数据库。如果这个数据库不存 在,那么 mongo 会自动建立一个名为
test
的数据库。上面的例子,由于 Mongo 服务器上没 有名为
test
的 db,因此,mongo 新建了一个空的名为
test
的 db。其中,没有任何 collection。
> show collections
>
2.database级操作
查看服务器上的数据库
> show dbs admin 0.000GB local 0.000GB
创建数据库
mongo 中创建数据库采用的是 use 命令和切换数据库命令一样,如果 use 后面跟的数据库名不存在,那么 mongo 将会新建该数据库。
不过,实际上只执行 use 命令后,mongo 是不会新建该数据库的,直到 你像该数据库中插入了数据。
> use qingbai switched to db qingbai > show dbs #到这里我们没有看到刚才新建的qingbai数据库 admin 0.000GB local 0.000GB > db.qingbai.insert({"name":"testdb"}) #该操作会在 qingbai 数据库中新建一个 hello 集合,并在其中插入一条记录。
WriteResult({ "nInserted" : 1 })
> show dbs #这样,便可以看到 mongo 的确创建了 qingbai 数据库,其中有一个 hello 集合。
admin 0.000GB
local 0.000GB
qingbai 0.000GB
切换数据库
> use qingbai;
switched to db qingbai
#mongo 中,db 代表当前使用的数据库。这样,db 就从原来的 test,变为现在的 qingbai 数据库,如果没有这个库,就会自动创建
查看当前数据库中的所有集合(也就是查看数据库中有哪些表)
> show collections
qingbai
查看当前所在数据库
下面哪种命令都行
> db test > db.getName(); test
删除数据库
> show dbs
admin 0.000GB
local 0.000GB
qingbai 0.000GB
test 0.000GB
> db
test
> db.dropDatabase() #删除当前所在数据库
{ "dropped" : "test", "ok" : 1 }
> show dbs
admin 0.000GB
local 0.000GB
qingbai 0.000GB
> db #可以看出删除 test 数据库之后,当前的 db 还是指向它,只有当切换数据库之后,test 才会彻底消失。
test
> use qingbai
switched to db qingbai
修复当前数据库
> db.repairDatabase();
{ "ok" : 1 }
查看当前数据库状态
> db.stats(); { "db" : "qingbai", "collections" : 1, "views" : 0, "objects" : 1, "avgObjSize" : 39, "dataSize" : 39, "storageSize" : 16384, "numExtents" : 0, "indexes" : 1, "indexSize" : 16384, "ok" : 1 }
查看当前db版本
> db.version(); 3.4.18
查看当前db的链接机器地址
> db.getMongo(); connection to 172.31.46.3:27888
从指定的机器上复制指定数据库数据到某个数据库
将172.31.46.38上的test1库的数据复制到指定本机的test1数据库中
> db.copyDatabase("test1", "qingbai", "172.31.46.38"); { "ok" : 1 }
3.collection 级操作(相当于关系型数据库中的表级)
创建collection(集合相当与表)操作
> db test1 > show collections test1 > db.createCollection("Hello") { "ok" : 1 } > show collections #查看集合 Hello test1
直接向一个不存在的 collection 中插入数据也能创建一个 collection
> db.hello2.insert({"name":"lfqy"}) #hello2就是集合名,insert后面就是要向collections 插入的数据 WriteResult({ "nInserted" : 1 }) > show collections Hello hello2 test1
删除collection操作
> show collections Hello hello2 test1 > db.Hello.drop() #返回 true 说明删除成功,false 说明没有删除成功。 true > show collections hello2 test1 > db.Hello3.drop() #不存在名为 Hello3 的 collection,因此,删除失败。 false
重命名 collection操作
将 hello2 集合重命名为 HELLO
> show collections hello2 test1 > db.hello2.renameCollection("HELLO") { "ok" : 1 } > show collections HELLO test1
建立索引在 HELLO 集合上,建立对 ID 字段的索引,1 代表升序 (这个目前不太理解)
> db.HELLO.ensureIndex({ID:1}) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 }
4.Record 级的操作
(就是表内记录级操作)
插入操作
向Hello集合(表)中插入记录
这是一种插入方法,,红色的字体是我们需要修改的
> db.Hello.insert({'name':'GalGadot','gender':'female','age':28,'salary':11000}) WriteResult({ "nInserted" : 1 }) > db.Hello.insert({'name':'Mikie Hara','gender':'female','age':26,'salary':7000}) WriteResult({ "nInserted" : 1 })同样也可以用 save 完成类似的插入操作
> db.Hello.save({'name':'Wentworth Earl Miller','gender':'male','age':41,'salary':33000})
WriteResult({ "nInserted" : 1 })
查找操作
查找集合中的所有记录
> db.Hello.find() { "_id" : ObjectId("5ee189567b52b050bfb020e9"), "name" : "GalGadot", "gender" : "female", "age" : 28, "salary" : 11000 } { "_id" : ObjectId("5ee1896e7b52b050bfb020ea"), "name" : "Mikie Hara", "gender" : "female", "age" : 26, "salary" : 7000 } { "_id" : ObjectId("5ee18a487b52b050bfb020eb"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 }
查询 age 为26 的数据
> db.Hello.find({"age":26}) { "_id" : ObjectId("5ee1896e7b52b050bfb020ea"), "name" : "Mikie Hara", "gender" : "female", "age" : 26, "salary" : 7000 }
查询 salary 大于 7000 的数据
> db.Hello.find({salary:{$gt:7000}}) { "_id" : ObjectId("5ee189567b52b050bfb020e9"), "name" : "GalGadot", "gender" : "female", "age" : 28, "salary" : 11000 } { "_id" : ObjectId("5ee18a487b52b050bfb020eb"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 }
查询 name 中包含
'ent'
的数据
> db.Hello.find({name:/ent/}) { "_id" : ObjectId("5ee18a487b52b050bfb020eb"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 }
查询Hello集合中name 以 G 打头的数据
> db.Hello.find({name:/^G/}) { "_id" : ObjectId("5ee189567b52b050bfb020e9"), "name" : "GalGadot", "gender" : "female", "age" : 28, "salary" : 11000 }
查询Hello集合中name 以 t 结尾的数据
> db.Hello.find({name:/t$/}) { "_id" : ObjectId("5ee189567b52b050bfb020e9"), "name" : "GalGadot", "gender" : "female", "age" : 28, "salary" : 11000 }
多条件“与”查询 age 小于 30,salary 大于 7000 的数据
> db.Hello.find({age:{$lt:30},salary:{$gt:7000}}) { "_id" : ObjectId("5ee189567b52b050bfb020e9"), "name" : "GalGadot", "gender" : "female", "age" : 28, "salary" : 11000 }
多条件“或”查询 age 小于 30,或者 salary 大于 10000 的记录
> db.Hello.find({$or:[{salary:{$gt:10000}},{age:{$lt:30}}]}) { "_id" : ObjectId("5ee189567b52b050bfb020e9"), "name" : "GalGadot", "gender" : "female", "age" : 28, "salary" : 11000 } { "_id" : ObjectId("5ee1896e7b52b050bfb020ea"), "name" : "Mikie Hara", "gender" : "female", "age" : 26, "salary" : 7000 } { "_id" : ObjectId("5ee18a487b52b050bfb020eb"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 }
将上面的
find
替换为 findOne()可以查找符合条件的第一条记录。
> db.Hello.findOne({$or:[{salary:{$gt:10000}},{age:{$lt:25}}]}) { "_id" : ObjectId("5ee189567b52b050bfb020e9"), "name" : "GalGadot", "gender" : "female", "age" : 28, "salary" : 11000 }
查询记录的指定字段查询 Hello 集合中所有记录的 name,age,salary,sex_orientation 字段,
这里的 1 表示显示此列的意思,也可以用
true
表示。
> db.Hello.find({},{name:1,age:1,salary:1,sex_orientation:true}) { "_id" : ObjectId("5ee189567b52b050bfb020e9"), "name" : "GalGadot", "age" : 28, "salary" : 11000 } { "_id" : ObjectId("5ee1896e7b52b050bfb020ea"), "name" : "Mikie Hara", "age" : 26, "salary" : 7000 } { "_id" : ObjectId("5ee18a487b52b050bfb020eb"), "name" : "Wentworth Earl Miller", "age" : 41, "salary" : 33000 }
查询指定字段的数据,并去重。
查询 gender 字段的数据,并去掉重复数据
> db.Hello.distinct('gender') [ "female", "male" ]
为了方便,mongo 也提供了 pretty print 工具,db.collection.pretty()或者是 db.collection.forEach(printjson)
就是让结果集输出更加美观
> db.Hello.find().pretty() { "_id" : ObjectId("5ee189567b52b050bfb020e9"), "name" : "GalGadot", "gender" : "female", "age" : 28, "salary" : 11000 } { "_id" : ObjectId("5ee1896e7b52b050bfb020ea"), "name" : "Mikie Hara", "gender" : "female", "age" : 26, "salary" : 7000 } { "_id" : ObjectId("5ee18a487b52b050bfb020eb"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 } >
显示结果集中的前 3 条记录
> db.Hello.find().limit(3) { "_id" : ObjectId("5ee189567b52b050bfb020e9"), "name" : "GalGadot", "gender" : "female", "age" : 28, "salary" : 11000 } { "_id" : ObjectId("5ee1896e7b52b050bfb020ea"), "name" : "Mikie Hara", "gender" : "female", "age" : 26, "salary" : 7000 } { "_id" : ObjectId("5ee18a487b52b050bfb020eb"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 }
查询第 1 条以后的所有数据
> db.Hello.find().skip(1) { "_id" : ObjectId("5ee1896e7b52b050bfb020ea"), "name" : "Mikie Hara", "gender" : "female", "age" : 26, "salary" : 7000 } { "_id" : ObjectId("5ee18a487b52b050bfb020eb"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 }
对结果集排序
升序
> db.Hello.find().sort({salary:1}) { "_id" : ObjectId("5ee1896e7b52b050bfb020ea"), "name" : "Mikie Hara", "gender" : "female", "age" : 26, "salary" : 7000 } { "_id" : ObjectId("5ee189567b52b050bfb020e9"), "name" : "GalGadot", "gender" : "female", "age" : 28, "salary" : 11000 } { "_id" : ObjectId("5ee18a487b52b050bfb020eb"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 }
降序
> db.Hello.find().sort({salary:-1}) { "_id" : ObjectId("5ee18a487b52b050bfb020eb"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 } { "_id" : ObjectId("5ee189567b52b050bfb020e9"), "name" : "GalGadot", "gender" : "female", "age" : 28, "salary" : 11000 } { "_id" : ObjectId("5ee1896e7b52b050bfb020ea"), "name" : "Mikie Hara", "gender" : "female", "age" : 26, "salary" : 7000 }
统计集合中的所有记录条数
> db.Hello.find().count() 3
查询符合条件的记录数
查询 salary 小于 4000 或大于 10000 的记录数
> db.Hello.find({$or: [{salary: {$lt:4000}}, {salary: {$gt:10000}}]}).count() 2
删除操作
删除整个集合中的所有数据
> db.Hello.find() { "_id" : ObjectId("5ee189567b52b050bfb020e9"), "name" : "GalGadot", "gender" : "female", "age" : 28, "salary" : 11000 } { "_id" : ObjectId("5ee1896e7b52b050bfb020ea"), "name" : "Mikie Hara", "gender" : "female", "age" : 26, "salary" : 7000 } { "_id" : ObjectId("5ee18a487b52b050bfb020eb"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 } > db.Hello.remove({}) WriteResult({ "nRemoved" : 3 }) > db.Hello.find()
mongo在删除数据的时候不支持 all * 全部删除选择{}就可以全部删除了
删除mongodb集合中的数据可以使用remove()函数。remove()函数可以接受一个查询文档作为可选参数来有选择性的删除符合条件的文档。
remove()函数不会删除集合本身,同时,原有的索引也同样不会被删除。
删除文档是永久性的,不能撤销,也不能恢复的。因此,在执行remove()函数前先用find()命令来查看下是否正确,是个比较好的习惯啦。
注意 db.collection.remove()和 drop()的区别,remove()只是删除了集合中所有的记录, 而集合中原有的索引等信息还在,而
drop()则把集合相关信息整个删除(包括索引)。
删除集合中符合条件的所有记录
> db.Hello.find() { "_id" : ObjectId("5ee1db6c1850bb8d0182929f"), "name" : "GalGadot", "gender" : "female", "age" : 28, "salary" : 11000 } { "_id" : ObjectId("5ee1db761850bb8d018292a0"), "name" : "Mikie Hara", "gender" : "female", "age" : 26, "salary" : 7000 } { "_id" : ObjectId("5ee1db811850bb8d018292a1"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 } > db.Hello.remove({name:'GalGadot'}) WriteResult({ "nRemoved" : 1 }) > db.Hello.find() { "_id" : ObjectId("5ee1db761850bb8d018292a0"), "name" : "Mikie Hara", "gender" : "female", "age" : 26, "salary" : 7000 } { "_id" : ObjectId("5ee1db811850bb8d018292a1"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 }
删除集合中符合条件的一条记录(这里会按顺序删除)
> db.Hello.find() { "_id" : ObjectId("5ee1db761850bb8d018292a0"), "name" : "Mikie Hara", "gender" : "female", "age" : 26, "salary" : 7000 } { "_id" : ObjectId("5ee1db811850bb8d018292a1"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 } { "_id" : ObjectId("5ee1dcd21850bb8d018292a2"), "name" : "qingbai", "gender" : "female", "age" : 26, "salary" : 7000 } > db.Hello.remove({salary :{$lt:30000}},1) WriteResult({ "nRemoved" : 1 }) > db.Hello.find() { "_id" : ObjectId("5ee1db811850bb8d018292a1"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 } { "_id" : ObjectId("5ee1dcd21850bb8d018292a2"), "name" : "qingbai", "gender" : "female", "age" : 26, "salary" : 7000 }
更新操作
赋值更新 db.collection.update(criteria, objNew, upsert, multi ) criteria:update 的查询条件,类似 sql update 查询内 where 后面的 objNew:update 的对象和一些更新的操作符(如$,$inc...)等,也可以理解为 sql update 查询内 set 后面的。 upsert : 如果不存在 update 的记录,是否插入 objNew,true 为插入,默认是 false,不插 入。 multi : mongodb 默认是 false,只更新找到的第一条记录,如果这个参数为 true,就把按条 件查出来多条记录全部更新。
> db.Hello.find() { "_id" : ObjectId("5ee1db811850bb8d018292a1"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 } { "_id" : ObjectId("5ee1dcd21850bb8d018292a2"), "name" : "qingbai", "gender" : "female", "age" : 26, "salary" : 7000 } { "_id" : ObjectId("5ee1e65f1850bb8d018292a3"), "name" : "test1", "gender" : "female", "age" : 27, "salary" : 7000 } { "_id" : ObjectId("5ee1e67f1850bb8d018292a4"), "name" : "test2", "gender" : "female", "age" : 27, "salary" : 7000 } > db.Hello.update({name:'test1'},{$set:{age:23}},false,true) #这里的{name:'test1'}就是查询条件,{$set:{age:23}}就是更新操作符,后面两个false和true的区别上面讲了。 WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.Hello.find() { "_id" : ObjectId("5ee1db811850bb8d018292a1"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 } { "_id" : ObjectId("5ee1dcd21850bb8d018292a2"), "name" : "qingbai", "gender" : "female", "age" : 26, "salary" : 7000 } { "_id" : ObjectId("5ee1e65f1850bb8d018292a3"), "name" : "test1", "gender" : "female", "age" : 23, "salary" : 7000 } { "_id" : ObjectId("5ee1e67f1850bb8d018292a4"), "name" : "test2", "gender" : "female", "age" : 27, "salary" : 7000 }
> db.Hello.update({name:'lfqy1'},{$set:{age:23}},true,true) #这里我们就发现后面两个false和true的区别了
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("5ee1e8a4b10fc47ffc3baecf")
})
> db.Hello.find()
{ "_id" : ObjectId("5ee1db811850bb8d018292a1"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 }
{ "_id" : ObjectId("5ee1dcd21850bb8d018292a2"), "name" : "qingbai", "gender" : "female", "age" : 26, "salary" : 7000 }
{ "_id" : ObjectId("5ee1e65f1850bb8d018292a3"), "name" : "test1", "gender" : "female", "age" : 23, "salary" : 7000 }
{ "_id" : ObjectId("5ee1e67f1850bb8d018292a4"), "name" : "test2", "gender" : "female", "age" : 27, "salary" : 7000 }
{ "_id" : ObjectId("5ee1e8a4b10fc47ffc3baecf"), "name" : "lfqy1", "age" : 23 }
增值更新
关于更新操作(db.collection.update(criteria, objNew, upsert, multi )),要说明的 是,如果 upsert 为
true
,那么在没有找到符合更新条件的情况下,mongo 会在集合中插入 一条记录其值满足更新条件的记录(其中的字段只有更新条件中涉及的字段,字段的值满足 更新条件),然后将其更新(注意,如果更新条件是$lt 这种不等式条件,那么 upsert 插入
> db.Hello.find() { "_id" : ObjectId("5ee1db811850bb8d018292a1"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 } { "_id" : ObjectId("5ee1dcd21850bb8d018292a2"), "name" : "qingbai", "gender" : "female", "age" : 26, "salary" : 7000 } { "_id" : ObjectId("5ee1e65f1850bb8d018292a3"), "name" : "test1", "gender" : "female", "age" : 23, "salary" : 7000 } { "_id" : ObjectId("5ee1e67f1850bb8d018292a4"), "name" : "test2", "gender" : "female", "age" : 27, "salary" : 7000 } { "_id" : ObjectId("5ee1e8a4b10fc47ffc3baecf"), "name" : "lfqy1", "age" : 23 } > db.Hello.update({gender:'female'},{$inc:{salary:50}},false,true) #这里的$inc作用是对某值,自增或者自减 WriteResult({ "nMatched" : 3, "nUpserted" : 0, "nModified" : 3 }) > db.Hello.find() { "_id" : ObjectId("5ee1db811850bb8d018292a1"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 } { "_id" : ObjectId("5ee1dcd21850bb8d018292a2"), "name" : "qingbai", "gender" : "female", "age" : 26, "salary" : 7050 } { "_id" : ObjectId("5ee1e65f1850bb8d018292a3"), "name" : "test1", "gender" : "female", "age" : 23, "salary" : 7050 } { "_id" : ObjectId("5ee1e67f1850bb8d018292a4"), "name" : "test2", "gender" : "female", "age" : 27, "salary" : 7050 } { "_id" : ObjectId("5ee1e8a4b10fc47ffc3baecf"), "name" : "lfqy1", "age" : 23 }
> db.Hello.update({gender:'test'},{$inc:{salary:50}},true,true) #这里我们就看出upsert(就是语句里红色加粗字体)为true和为false的区别了
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("5ee1ef0eb10fc47ffc3baed0")
})
> db.Hello.find()
{ "_id" : ObjectId("5ee1db811850bb8d018292a1"), "name" : "Wentworth Earl Miller", "gender" : "male", "age" : 41, "salary" : 33000 }
{ "_id" : ObjectId("5ee1dcd21850bb8d018292a2"), "name" : "qingbai", "gender" : "female", "age" : 26, "salary" : 7050 }
{ "_id" : ObjectId("5ee1e65f1850bb8d018292a3"), "name" : "test1", "gender" : "female", "age" : 23, "salary" : 7050 }
{ "_id" : ObjectId("5ee1e67f1850bb8d018292a4"), "name" : "test2", "gender" : "female", "age" : 27, "salary" : 7050 }
{ "_id" : ObjectId("5ee1e8a4b10fc47ffc3baecf"), "name" : "lfqy1", "age" : 23 }
{ "_id" : ObjectId("5ee1ef0eb10fc47ffc3baed0"), "gender" : "test", "salary" : 50 }
5.用户相关操作
mongodb用户权限列表:
Read:允许用户读取指定数据库
readWrite:允许用户读写指定数据库
dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
userAdmin:允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户
clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。
readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。
root:只在admin数据库中可用。超级账号,超级权限
mongodb有一个用户管理机制,简单描述为,有一个管理用户组,这个组的用户是专门为管理普通用户而设的,暂且称之为管理员。
管理员通常没有数据库的读写权限,只有操作用户的权限, 因此我们只需要赋予管理员userAdminAnyDatabase角色即可
另外管理员账户必须在admin数据库下创建,3.0版本后没有admin数据库,但我们可以手动use一个 > show dbs local 0.000GB test1 0.000GB > use admin switched to db admin > db admin > db.system.users.find() #查看数据库的用户列表
#创建一个用户名为super, 密码为superpwd的管理员账户:
成功则会提示Successfully
注意:这里使用createUser()方法来创建,addUser()方法已经被废弃
> db.createUser({user:"super",pwd:"superpwd",roles:[ { role: "userAdminAnyDatabase", db: "admin" } ]}); Successfully added user: { "user" : "super", "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] } > db.system.users.find() #这里我们看到管理员已经被创建 { "_id" : "admin.super", "user" : "super", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "PPw4NNCWlHhCgba1md9Mpg==", "storedKey" : "CsAtFG6fd4yd9KXLYo0e88oACXs=", "serverKey" : "t59MTDEGVxLo6AOnW4VhEBcF9G8=" } }, "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ]
#创建管理员后,需要给管理员授权,否则无权限操作用户
#如果结果返回1,则表示授权成功,返回0则表示失败
> db.auth('super','superpwd') 1
这里一般小伙伴会有疑问,我好像不通过管理员登录,也可以执行管理员的操作。
这是因为配置文件mongod.conf中有一项配置参数auth=false,这个代表可以默认是可以不通过权限操作的,所以一般当我们通过用户管理mongodb了,还需要在配置
文件里加上auth=true 然后重启。这样后续操作就可以通过用户进行管理了
使用管理员账户创建普通用户
普通用户由管理员创建,并授权。通常需要指定某个数据库来操作。
我们这里创建一个blog数据库,并且给这个数据库添加一个用户,用户名为develop,密码为developpwd,
> use blog switched to db blog > db.createUser({user:"develop",pwd:"developpwd",roles:[ { role: "readWrite", db: "blog" } ]}); Successfully added user: { "user" : "develop", "roles" : [ { "role" : "readWrite", "db" : "blog" } ] } > db.auth('develop','developpwd') 1
验证普通用户登录数据库,如果密码正确,就会正常进入数据库,错误的话,就会报第二条命令执行后的错误
[root@2-no ~]# mongo mongodb://develop:developpwd@172.31.46.38:27017/blog [root@2-no ~]# mongo mongodb://develop:developpd@172.31.46.38:27017/blog MongoDB shell version: 3.2.22 connecting to: mongodb://develop:developpd@172.31.46.38:27017/blog 2020-06-11T23:34:02.881+0800 E QUERY [thread1] Error: Authentication failed. : connect@src/mongo/shell/mongo.js:223:14 @(connect):1:6 exception: connect failed
用户操作总结
创建用户 db.createUser({ user:用户名, pwd:密码, roles:[ { role:权限类型, db:可访问的db} ] })
查看用户列表 db.system.users.find() 查看某个用户信息 db.runCommand({usersInfo:用户名}) 修改用户信息 db.runCommand( { updateUser:用户名, pwd:密码, customData:{title:"xxx"……} } )
修改用户密码 db.changeUserPassword(‘user’,’pwd’);
删除用户 db.system.users.remove({user:”username”});
七、yum的方式安装mongodb
1.创建repo
[root@2-no src]# cat /etc/yum.repos.d/mongodb-org-3.2.repo [mongodb-org-3.2] name=MongoDB Repository baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.2/x86_64/ gpgcheck=0 enabled=1
2.安装MongoDB和相关工具
[root@2-no src]# yum install -y mongodb-org
3.启动Mongdb
[root@2-no src]# service mongod start Starting mongod (via systemctl): [ OK ] [root@2-no src]# chkconfig mongod on [root@2-no src]# lsof -i:27017 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME mongod 28707 mongod 6u IPv4 46736011 0t0 TCP localhost:27017 (LISTEN)
日志文件:/var/log/mongodb/mongod.log
配置文件:/etc/mongod.conf
数据目录:/var/lib/mongo/
4.配置文件解释
[root@2-no src]# cat /etc/mongod.conf # mongod.conf # for documentation of all options, see: # http://docs.mongodb.org/manual/reference/configuration-options/ # where to write logging data. systemLog: destination: file logAppend: true #以追加方式写入日志
path: /var/log/mongodb/mongod.log # Where and how to store data. storage: dbPath: /var/lib/mongo#数据库文件保存位置
journal: enabled: true # engine: # mmapv1: # wiredTiger: # how the process runs processManagement: fork: true # fork and run in background pidFilePath: /var/run/mongodb/mongod.pid # location of pidfile # network interfaces net: port: 27017 #端口号 bindIp: 127.0.0.1 # Listen to local interface only, comment to listen on all interfaces. #security: #operationProfiling: #replication: #sharding: ## Enterprise-Only Options #auditLog: #snmp: