21.4 MongoDB介绍
什么是MongoDB
MongoDB也是NoSQL的一种,它是一个基于分布式文件存储的文档型数据库,由C++语言编写。因为是文档型数据库,所以它是非关系数据库中功能最丰富、最像关系数据库的。
官方网站 ,最新版本4.0.1。
MongoDB将数据存储为一个文档,数据结构将键值(key-value)对组成,MongoDB文档类似于JSON对象,字段值可以包含其它文档、数组及文档数组。
- 基本概念:
文档(document):MongoDB中数据的基本单元,非常类似于关系型数据库系统中的行,但是比行要复杂的多。
集合(collection):一组文档,如果说MongoDB中的文档类似于关系型数据库中的行,那么集合就如同表。
MongoDB的单个计算机可以容纳多个独立的数据库,每一个数据库都有自己的集合和权限;
MongoDB自带简洁但功能强大的JavaScript shell,这个工具对于管理MongoDB实例和操作数据作用非常大;
每一个文档都有一个特殊的键”_id”,它在文档所处的集合中是唯一的,相当于关系数据库中的表的主键。
MongoDB的特点是高性能、易部署、易使用,存储数据非常方便,它的主要特性有:
面向集合存储,易存储对象类型的数据
模式自由
支持动态查询
支持完全索引,包含内部对象
支持复制和故障恢复
使用高效的二进制数据存储,包括大型对象
文件存储格式为BSON(一种JSON的扩展)
MongoDB安装
- 安装MongoDB:
# cd /etc/yum.repos.d/
# vim mongo.repo
[mongodb-org-3.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc
# yum install -y mongodb-org
连接MongoDB
- 启动服务:
# systemctl start mongod
# ps aux |grep mongod
mongod 1522 0.8 0.9 972380 37512 ? Sl 10:30 0:00 /usr/bin/mongod -f /etc/mongo.conf
# netstat -lntp |grep mongod
tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN 1522/mongod
- 进入mongodb shell:
# mongo
MongoDB shell version v3.4.16
connecting to: mongodb://127.0.0.1:27017 #显示IP及监听端口
MongoDB server version: 3.4.16
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
http://docs.mongodb.org/
Questions? Try the support group
http://groups.google.com/group/mongodb-user
Server has startup warnings:
2018-08-25T10:30:18.431+0800 I CONTROL [initandlisten]
2018-08-25T10:30:18.431+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2018-08-25T10:30:18.431+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
2018-08-25T10:30:18.431+0800 I CONTROL [initandlisten]
2018-08-25T10:30:18.431+0800 I CONTROL [initandlisten]
2018-08-25T10:30:18.431+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2018-08-25T10:30:18.431+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2018-08-25T10:30:18.431+0800 I CONTROL [initandlisten]
2018-08-25T10:30:18.431+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2018-08-25T10:30:18.431+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' #关于内核的警告,可忽略
2018-08-25T10:30:18.431+0800 I CONTROL [initandlisten]
>
如果监听端口不是默认的27017,则在连接的时候需要加--port
选项,如:
mongo --port 27018
远程连接mongodb,需要加--host
,如:
mongo --host 127.0.0.1
如果设置了验证,则在连接的时候需要带上用户名和密码,如:
mongo -u用户名 -p密码 --authenticationDatabase 数据库名 #和mysql类似
MongoDB用户管理
- 管理用户:
> use admin #use切换库,只有在admin库中才可以操作用户管理
switched to db admin
#创建用户并授权;customData表示对用户的描述,可省略;roles表示角色,指定库的权限
> db.createUser( {
user: "admin", customData: {
description: "superuser"}, pwd: "admin123", roles: [ {
role: "root", db:"admin" } ] } )
Successfully added user: {
"user" : "admin",
"customData" : {
"description" : "superuser"
},
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
> db.system.users.find() #列出所有用户,需要切换到admin库
{
"_id" : "admin.admin", "user" : "admin", "db" : "admin", "credentials" : {
"SCRAM-SHA-1" : {
"iterationCount" : 10000, "salt" : "J8r1+mWlE53xnEKSiQ98hA==", "storedKey" : "7dl9ZmLoj8AHTb7LguX/w4C9X9U=", "serverKey" : "ZMpgYfQMxGAULJh9a5rFijPny2E=" } }, "customData" : {
"description" : "superuser" }, "roles" : [ {
"role" : "root", "db" : "admin" } ] }
#admin.admin表示admin库的admin用户
> show users #列出当前库下所有的用户
{
"_id" : "admin.admin",
"user" : "admin",
"db" : "admin",
"customData" : {
"description" : "superuser"
},
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
> db.createUser({
user:"lzx",pwd:"123123",roles:[{
role:"read",db:"testdb"}]}) #创建lzx用户,设为read角色,针对的库是testdb
Successfully added user: {
"user" : "lzx",
"roles" : [
{
"role" : "read",
"db" : "testdb"
}
]
}
> show users #查看新创建的用户
{
"_id" : "admin.admin",
"user" : "admin",
"db" : "admin",
"customData" : {
"description" : "superuser"
},
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
{
"_id" : "admin.lzx",
"user" : "lzx",
"db" : "admin",
"roles" : [
{
"role" : "read",
"db" : "testdb"
}
]
}
> db.dropUser('lzx') #删除刚创建的lzx用户
true
> show users
{
"_id" : "admin.admin",
"user" : "admin",
"db" : "admin",
"customData" : {
"description" : "superuser"
},
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
} #新创建的用户已经消失
新增用户之后,若要用户生效,还需要编辑启动脚本:
# vim /usr/lib/systemd/system/mongod.service
Environment="OPTIONS=--auth -f /etc/mongod.conf"
# systemctl daemon-reload
# systemctl restart mongod
# ps aux |grep mongod
mongod 8049 17.8 1.0 972380 41420 ? Sl 14:03 0:02 /usr/bin/mongod --auth -f /etc/mongod.conf
# mongo --host 127.0.0.1 --port 27017
MongoDB shell version v3.4.16
connecting to: mongodb://127.0.0.1:27017/
MongoDB server version: 3.4.16
> use admin
switched to db admin
> show users #刚刚登录的用户没有权限执行命令
2018-08-25T14:06:39.482+0800 E QUERY [thread1] Error: not authorized on admin to execute command {
usersInfo: 1.0 } :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DB.prototype.getUsers@src/mongo/shell/db.js:1539:1
shellHelper.show@src/mongo/shell/utils.js:771:9
shellHelper@src/mongo/shell/utils.js:678:15
@(shellhelp2):1:1
# mongo --host 127.0.0.1 --port 27017 -u 'admin' -p 'admin123' --authenticationDatabase "admin" #指定用户密码和库,再次登录
MongoDB shell version v3.4.16
connecting to: mongodb://127.0.0.1:27017/
MongoDB server version: 3.4.16
Server has startup warnings:
2018-08-25T14:03:27.518+0800 I CONTROL [initandlisten]
2018-08-25T14:03:27.518+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2018-08-25T14:03:27.518+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2018-08-25T14:03:27.518+0800 I CONTROL [initandlisten]
2018-08-25T14:03:27.518+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2018-08-25T14:03:27.518+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2018-08-25T14:03:27.518+0800 I CONTROL [initandlisten]
> use admin
switched to db admin
> show users #再次执行命令就没问题了
{
"_id" : "admin.admin",
"user" : "admin",
"db" : "admin",
"customData" : {
"description" : "superuser"
},
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
> use db1
switched to db db1
> db.createUser({
user:"test1",pwd:"123123",roles:[{
role:"readWrite",db:"db1"},{
role:"read",db:"db2"}]}) #创建用户test1,对db1库有读写权限,对db2库只读
Successfully added user: {
"user" : "test1",
"roles" : [
{
"role" : "readWrite",
"db" : "db1"
},
{
"role" : "read",
"db" : "db2"
}
]
}
先use db1
,表示用户在db1库中创建,用户的信息会跟随数据库。
> db.auth('test1','123123') #在命令行认证用户
1 #返回1说明认证成功
> use db2
switched to db db2
> db.auth('test1','123123')
Error: Authentication failed.
0 #db2下认证失败
MongoDB中有这些角色:
read:允许用户读取指定数据库
readWrite:允许用户读写指定数据库
dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
userAdmin:允许用户向system.users集合写入,可以在指定数据库里创建、删除和管理用户
clusterAdmin:只在admin数据中可用,赋予用户所有分片和复制集相关函数的管理权限
readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase:只在admin数据库中可用,赋予所有数据库的userAdmin权限
dbAdminAnyDatabase:只在admin数据库中可用,赋予所有数据库的dbAdmin权限
root:只在admin数据库中可用。超级账号,超级权限
MongoDB创建集合、数据管理
> use db1
switched to db db1
> db.createCollection("mycol",{
capped:true,size:6142800,max:10000})
{
"ok" : 1 }
创建集合;集合名为mycol;option可选,用来配置集合的参数。
capped true/false (可选),如果为true,则启用封顶集合。封顶集合是固定大小的集合,当它达到最大大小,会自动覆盖最早的条目。如果指定为true,也需要指定尺寸参数;
size(可选),指定最大大小字节封顶集合。如果capped是true,那么就必须指定这个字段,单位B;
max(可选),指定封顶集合允许在文件的最大数量。
> show tables #查看集合
mycol
> show collections #这样也可以查看集合
mycol
> db.Account.insert({
AccountID:1,UserName:"123",password:"123456"}) #向集合中插入数据,若集合不存在,则自动创建
WriteResult({
"nInserted" : 1 })
> show collections
Account
mycol
> db.Account.insert({
AccountID:2,UserName:"aaa",password:"aaaaaa"}) #再插入一个文档
WriteResult({
"nInserted" : 1 })
> show collections
Account #仍属于Account集合
mycol
> db.Account.update({
AccountID:1},{
"$set":{
"Age":20}}) #更新集合中AccountID:1文档的数据
WriteResult({
"nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.Account.find() #查看所有文档
{
"_id" : ObjectId("5b80feb826e56a836ac4d168"), "AccountID" : 1, "UserName" : "123", "password" : "123456", "Age" : 20 }
{
"_id" : ObjectId("5b8100cc26e56a836ac4d169"), "AccountID" : 2, "UserName" : "aaa", "password" : "aaaaaa" }
> db.Account.find({
AccountID:1}) #指定条件查询
{
"_id" : ObjectId("5b80feb826e56a836ac4d168"), "AccountID" : 1, "UserName" : "123", "password" : "123456", "Age" : 20 }
> db.Account.remove({
AccountID:1})
WriteResult({
"nRemoved" : 1 }) #指定条件删除文档
> db.Account.find()
{
"_id" : ObjectId("5b8100cc26e56a836ac4d169"), "AccountID" : 2, "UserName" : "aaa", "password" : "aaaaaa" }
> db.Account.drop() #删除集合Account中所有文档,即删除集合
true
> show collections
mycol
> db.mycol.drop()
true
> show collections
> db.col123.insert({
AccountID:1,UserName:"123",password:"123456"})
WriteResult({
"nInserted" : 1 })
> db.printCollectionStats() #查看所有集合状态
col123
{
"ns" : "db1.col123",
"size" : 80,
"count" : 1,
"avgObjSize" : 80,
"storageSize" : 16384,
"capped" : false,
"wiredTiger" : {
"metadata" : {
"formatVersion" : 1
},
"creationString" : "access_pattern_hint=none,allocation_size=4KB,app_metadata=(formatVersion=1),block_allocation=best,block_compressor=snappy,cache_resident=false,checksum=on,colgroups=,collator=,columns=,dictionary=0,encryption=(keyid=,name=),exclusive=false,extractor=,format=btree,huffman_key=,huffman_value=,ignore_in_memory_cache_size=false,immutable=false,internal_item_max=0,internal_key_max=0,internal_key_truncate=true,internal_page_max=4KB,key_format=q,key_gap=10,leaf_item_max=0,leaf_key_max=0,leaf_page_max=32KB,leaf_value_max=64MB,log=(enabled=true),lsm=(auto_throttle=true,bloom=true,bloom_bit_count=16,bloom_config=,bloom_hash_count=8,bloom_oldest=false,chunk_count_limit=0,chunk_max=5GB,chunk_size=10MB,merge_max=15,merge_min=0),memory_page_max=10m,os_cache_dirty_max=0,os_cache_max=0,prefix_compression=false,prefix_compression_min=4,source=,split_deepen_min_child=0,split_deepen_per_child=0,split_pct=90,type=file,value_format=u",
"type" : "file",
"uri" : "statistics:table:collection-4-6088379814182883756",
"LSM" : {
"bloom filter false positives" : 0,
"bloom filter hits" : 0,
"bloom filter misses" : 0,
"bloom filter pages evicted from cache" : 0,
"bloom filter pages read into cache" : 0,
"bloom filters in the LSM tree" : 0,
"chunks in the LSM tree" : 0,
"highest merge generation in the LSM tree" : 0,
"queries that could have benefited from a Bloom filter that did not exist" : 0,
"sleep for LSM checkpoint throttle" : 0,
"sleep for LSM merge throttle" : 0,
"total size of bloom filters" : 0
},
"block-manager" : {
"allocations requiring file extension" : 3,
"blocks allocated" : 3,
"blocks freed" : 0,
"checkpoint size" : 4096,
"file allocation unit size" : 4096,
"file bytes available for reuse" : 0,
"file magic number" : 120897,
"file major version number" : 1,
"file size in bytes" : 16384,
"minor version number" : 0
},
"btree" : {
"btree checkpoint generation" : 22,
"column-store fixed-size leaf pages" : 0,
"column-store internal pages" : 0,
"column-store variable-size RLE encoded values" : 0,
"column-store variable-size deleted values" : 0,
"column-store variable-size leaf pages" : 0,
"fixed-record size" : 0,
"maximum internal page key size" : 368,
"maximum internal page size" : 4096,
"maximum leaf page key size" : 2867,
"maximum leaf page size" : 32768,
"maximum leaf page value size" : 67108864,
"maximum tree depth" : 3,
"number of key/value pairs" : 0,
"overflow pages" : 0,
"pages rewritten by compaction" : 0,
"row-store internal pages" : 0,
"row-store leaf pages" : 0
},
"cache" : {
"bytes currently in the cache" : 952,
"bytes read into cache" : 0,
"bytes written from cache" : 175,
"checkpoint blocked page eviction" : 0,
"data source pages selected for eviction unable to be evicted" : 0,
"hazard pointer blocked page eviction" : 0,
"in-memory page passed criteria to be split" : 0,
"in-memory page splits" : 0,
"internal pages evicted" : 0,
"internal pages split during eviction" : 0,
"leaf pages split during eviction" : 0,
"modified pages evicted" : 0,
"overflow pages read into cache" : 0,
"overflow values cached in memory" : 0,
"page split during eviction deepened the tree" : 0,
"page written requiring lookaside records" : 0,
"pages read into cache" : 0,
"pages read into cache requiring lookaside entries" : 0,
"pages requested from the cache" : 1,
"pages written from cache" : 2,
"pages written requiring in-memory restoration" : 0,
"tracked dirty bytes in the cache" : 0,
"unmodified pages evicted" : 0
},
"cache_walk" : {
"Average difference between current eviction generation when the page was last considered" : 0,
"Average on-disk page image size seen" : 0,
"Clean pages currently in cache" : 0,
"Current eviction generation" : 0,
"Dirty pages currently in cache" : 0,
"Entries in the root page" : 0,
"Internal pages currently in cache" : 0,
"Leaf pages currently in cache" : 0,
"Maximum difference between current eviction generation when the page was last considered" : 0,
"Maximum page size seen" : 0,
"Minimum on-disk page image size seen" : 0,
"On-disk page image sizes smaller than a single allocation unit" : 0,
"Pages created in memory and never written" : 0,
"Pages currently queued for eviction" : 0,
"Pages that could not be queued for eviction" : 0,
"Refs skipped during cache traversal" : 0,
"Size of the root page" : 0,
"Total number of pages currently in cache" : 0
},
"compression" : {
"compressed pages read" : 0,
"compressed pages written" : 0,
"page written failed to compress" : 0,
"page written was too small to compress" : 2,
"raw compression call failed, additional data available" : 0,
"raw compression call failed, no additional data available" : 0,
"raw compression call succeeded" : 0
},
"cursor" : {
"bulk-loaded cursor-insert calls" : 0,
"create calls" : 1,
"cursor-insert key and value bytes inserted" : 81,
"cursor-remove key bytes removed" : 0,
"cursor-update value bytes updated" : 0,
"insert calls" : 1,
"next calls" : 0,
"prev calls" : 1,
"remove calls" : 0,
"reset calls" : 2,
"restarted searches" : 0,
"search calls" : 0,
"search near calls" : 0,
"truncate calls" : 0,
"update calls" : 0
},
"reconciliation" : {
"dictionary matches" : 0,
"fast-path pages deleted" : 0,
"internal page key bytes discarded using suffix compression" : 0,
"internal page multi-block writes" : 0,
"internal-page overflow keys" : 0,
"leaf page key bytes discarded using prefix compression" : 0,
"leaf page multi-block writes" : 0,
"leaf-page overflow keys"