MongoDB常用命令帅哥特供版

MongoDB常用命令帅哥特供版

  • 没错这里说的帅哥就是我自己

MongoDB常用命令

常用命令

命令 参考释义
help 显示基本操作命令
db.help() 显示数据库操作命令
db.collection.help() 显示集合操作命令
sh.help() 显示数据库分片操作命令
rs.help() 显示副本集操作命令
help admin 显示管理员操作命令
help connect 显示连接数据库命令
help keys 显示快捷键
help misc 显示其他该知道的东西
show dbs 显示所有数据库列表
show collections 显示当前数据库所有集合列表
show users 显示所有用户列表
show logs 显示所有日志名称列表(默认为global)
use dbname 切换/创建数据库(若不存在则自动创建)

数据库相关

命令 参考释义
db.cloneCollection() 在MongoDB实例之间复制集合数据
db.cloneDatabase() 从指定主机上克隆数据库到当前数据库
db.commandHelp() 返回数据库命令的帮助信息
db.copyDatabase() 从指定的主机上复制指定数据库数据到某个数据库
db.createCollection() 创建一个新的集合
db.currentOp() 显示当前正在进行的操作。
db.dropDatabase() 删除当前数据库。
db.fsyncLock() 刷新写入磁盘并锁定该数据库,以防止写入操作,并协助备份操作。
db.fsyncUnlock() 允许继续进行写入锁住的数据库(解锁)
db.getCollection() 返回一个集合对象。需要传递一个在数据库中存在的一个有效的集合名称
db.getCollectionInfos() 返回当前数据库中的所有集合信息。
db.getCollectionNames() 列出当前数据库中的所有集合。
db.getLastError() 检查并返回最后一个操作的状态。
db.getLastErrorObj() 返回上次操作状态的文件。
db.getLogComponents() 返回日志消息详细级别。
db.getMongo() 返回MongoDB当前连接的连接对象。
db.getName() 返回当前数据库的名称。(也可以直接使用db;命令)
db.getPrevError() 返回包含自上次错误复位所有的错误状态文件。
db.hostInfo() 返回当前数据库主机系统的相关信息
db.killOp() 终止指定的操作。
db.listCommands() 显示公共数据库的命令列表。
db.logout() 注销登录
db.repairDatabase() 修复当前数据库
db.resetError() 重置db.getPrevError()和getPrevError返回的错误信息。
db.runCommand() 运行一个数据库命令。
db.serverStatus() 返回当前数据库状态的概要
db.setLogLevel() 设置一个单独的日志信息级别。
db.setProfilingLevel() 修改当前数据库的分析级别。
db.shutdownServer() 关闭当前数据库运行实例或安全停止有关操作进程
db.stats() 返回在当前数据库的状态报告。
db.version() 返回当前数据库的版本信息

集合相关

命令 参考释义
db.collection.bulkWrite() 批量写入
db.collection.count() 返回集合总数或匹配查询的结果集总数
db.collection.copyTo() 已过时。现此操作被封装在两个数据库实例之间的复制数据中
db.collection.createIndex() 创建一个集合索引
db.collection.dataSize() 返回集合的大小
db.collection.deleteOne() 删除集合中的一个文档
db.collection.deleteMany() 删除集合中的多个文档。
db.collection.distinct() 返回具有指定字段不同值的文档(去除指定字段的重复数据)
db.collection.drop() 删除当前数据库中的collection集合
db.collection.dropIndex() 删除一个集合中的指定索引
db.collection.dropIndexes() 删除一个集合中的所有索引
db.collection.ensureIndex() 已过时。现使用db.collection.createIndex() 。
db.collection.explain() 返回各种方法的查询执行信息
db.collection.find() 查询集合,无参数则查询所有,并返回一个游标对象。
db.collection.findAndModify() 查询并修改
db.collection.findOne() 查询单条数据
db.collection.findOneAndDelete() 查询单条数据并删除
db.collection.findOneAndReplace() 查询单条数据并替换
db.collection.findOneAndUpdate() 查询单条数据并更新
db.collection.getIndexes() 返回当前集合的所有索引数组
db.collection.group() 提供简单的数据聚合功能
db.collection.insert() 在当前集合插入一条或多条数据(或叫文档)
db.collection.insertOne() 在当前集合插入一条数据
db.collection.insertMany() 在当前集合插入多条数据
db.collection.isCapped() 判断集合是否为定容量
db.collection.reIndex() 重建当前集合的所有索引
db.collection.replaceOne() 替换集合中的一个文档(一条数据)
db.collection.remove() 从当前集合删除数据
db.collection.renameCollection() 重命名集合名称
db.collection.save() 在当前集合插入一条数据,同insert()方法的区别:当要插入的数据已存在时,save会执行更新操作,而insert方法会忽略当前操作
db.collection.stats() 返回当前集合的状态
db.collection.storageSize() 返回当前集合已使用的空间大小
db.collection.totalSize() 返回当前集合的总占用空间,包括所有文件和所有索引
db.collection.totalIndexSize() 返回当前集合所有的索引所占用的空间大小
db.collection.update() 修改集合中的数据。
db.collection.updateOne() 修改集合中的一条数据。
db.collection.updateMany() 修改集合中的多条数据。
db.collection.validate() 执行对集合验证操作。

Mongodb初始化操作

注解

默认: mongo的数据库和集合的创建是隐式创建, 当进行创建集合中的字段时,自定建立该数据库,如: db.c1.insert({});即同时创建了c1的集合

手动: 显式创建集合db.createCollection('c1');创建c1集合

安装

Mac 下直接使用brew
Ubuntu 直接使用apt-get install mongodb
MongoDB默认使用27017端口

关闭服务器

关闭服务器:
    mongod  --shutdown  --dbpath /database/mongodb/data/
    mongod 命令的 shutdown 选项能干净的关闭 MongoDB 服务。

启动

Mac下:
  如果找不到命令直接进入:
        /usr/local/Cellar/mongodb/3.4.4/bin
    
1.启动服务(MacOS&linux除路径外都一样)
    ./mongod --dbpath=/usr/local/Cellar/mongodb/3.4.4/data(指定的数据库保存位置) --logpath=/usr/local/Cellar/mongodb/3.4.4/log/log(指定的日志保存位置,这里必须指定到文件而不是目录,否则会报错) --fork(后台运行)
    
我在Mac中使用的启动服务的方式
/usr/local/Cellar/mongodb/3.4.4/bin/mongod --dbpath=/usr/local/Cellar/mongodb/3.4.4/data --logpath=/usr/local/Cellar/mongodb/3.4.4/log/log
    
    启动注意:
        mongodb目录下的data和log目录我在20170509安装时db.version()3.4.4 MacOX系统时,目录下没有这个目录.需要自行建立.
    
2.连接数据库(命令行操作)
    ./mongo
    
3.关闭数据库
    可以使用Killall或pkill 决不能用Kill -9
    或者:
    如果处理连接状态,那么直接可以通过在 admin 库中发送 db.shutdownServer()指令去停止 MongoDB 实例;
    
4.mongod启动命令常用参数
    --dbpath 指定数据库目录
    --port  指定数据库的端口,默认27017
    --bind_ip   绑定IP
    --directoryperdb为每个db创建一个独立子目录
    --logpath   自定日志存放目录
    --logappend对存在的日志追加,如果没有这个选项,新日志将会覆盖旧的日志
    --pidfilepath指定进程文件路径,如果不指定,将不产生进程文件
    --keyFile集群模式的关键标识
    --journal 启用日志
    --nssize 指定.ns文件的大小, 单位mb默认是16M,最大2GB
    --maxConns 最大的并发连接数
    --notablescan不允许进行表扫描
    --noprealloc关闭数据文件的预分配功能
    --fork以后台Daemon形式运行服务
    --config 指定配置文件
    --smallfiles 使用较小的默认文件大小
    --repair 通过丢弃无效或损坏的数据重新构建数据库和索引,这些数据可能由于意外的系统重新启动或崩溃而出现。
    比如非法关闭的时候第二次启动报lock文件错, rm /安装目录/mongodb/mongo.lock && ./mongod  --repair
    跟多参数利用Mongod --help进行查看

逻辑结构

MysqlMongodb
database(库)database(库)
table(表)collection(集合)
row(行)document(文档)
column(列)field(域)
index(索引)index(索引)
table joins(连表)
primary key(主键)primary key(主键)

mongodb常用数据类型

1.null 
    Null类型用来标识空值或不存在的字段
    如:{'one':null}

2.bool
    布尔型有两种值true和false
    如:{'one':true}

3.32位整数
    mongoDB的控制台使用js引擎进行输入,而js仅支持64位浮点数,所以32位整数会被转义.

4.64位整数
    64位整数和32位整数一样,在MongoDB控制台使用时会被转义为64位浮点数.
    
5.64位浮点数
    MongoDB控制台数字的默认类型
    如:{"one":2.02}{'one':10}
    
6.字符串
    utf字符串都可以表示为字符串类型的数据
    如:{"one":"Hello World"}

7.符号
    在MongoDB控制台中不支持这种类型,将自动转义为字符串
    
8.ObjectId类型
    对象ID是文档中唯一的12位的ID
    0|1|2|3|4|5|6|7|8|9|10|11
    时间戳 |机器 |PID |计数器
    如: ObjectId("59115566f4d5125386de535e")
    
9.日期
    注意: 使用的时候加上 new
    如: {"one":new Data()}
    
10.正则表达式
    文档键值可以包含正则表达式, 其正则表达式采用js语法来表示
    如: {"one":/ho/i}
    
11.代码
    文档中可以包含js代码
    如: {"one":function(){/*....../*}}
    
12.数组
    文档中键值可以标识为数组, 在数组内还可以嵌套数组
    如: {"x":["a","b",["c","d"]]}
    
13,内嵌文档
    文档可以包含别的文档,可以作为值嵌入到父文档中
    如: {"x"{"name":"Tom","age":20}}


常用命令(控制台中常用的操作命令)

db.version();                       查看版本号
show dbs;                           查看所有库(同时显示库大小)
show databases;                     查看所有库
db.getCollectionInfos({字段名: /正则/}) 返回具有当前数据库的集合信息(即集合名称和选项)的文档数组。
db.getCollectionNames()            返回一个数组,该数组包含当前数据库中所有集合的名称。
如果要过滤可以使用:
结尾不是usdt不显示,这个其实就是JS的函数
db.getCollectionNames().filter(function(el) {return el.indexOf('usdt') !== -1})

db.copyDatabase('oldName','newName')复制库
db;                                 查看当前所在库
use 库名;                           选择库
show collections;                   查看所有集合
db.shutdownServer();
关闭服务器(需要先行 use 到 admin)

db.c1.stats();                      查看集合状态
db.c1.insert(json格式);             插入数据(此处db代表当前库)(c1为集合)
db.c1.find([where]);                查询时数据[条件](c1为集合)
db.c1.update({where},{update});     修改数据

db.c1.drop();                       删除集合及其文档
db.c1.remove({});                   删除集合中的文档,
db.dropDatabase();                  删除当前库

固定集合
db.c1.isCapped();                   判断是否是固定集合
db.c1.stats();                      查看集合状态

用户操作:
db.system.users.find();             查看用户列表
show users;                         查看所有用户


更多命令使用可以在mongo中使用help查看;
想知道当前数据库支持那些方法: db.help();
想知道当前集合支持那些方法: db.user.help();user为合集名;

索引

system.indexs
    该库里面的集合中的所有_id(主键索引)所有都放在这里面.

mongodb增删改查的高级应用(Capped固定集合&GridFs大文件管理)

固定集合Capped Collection

  • 固定集合介绍

capped collections是性能出色的有着固定大小的集合,以LRU(Least Recently Used最近最少使用)规则和插入顺序进行age-out(老化移除)处理,自动维护集合中对象的插入顺序,在创建时要预先指定大小,如果空间用完,新添加的对象将会取代集合中最老的对象.永远保持最新数据.

功能特点:
普通集合:
	随着内容的增多,空间自动增大.

固定集合:
可以插入及更新,但更新不能超出collection的大小,否则更新失败.不允许删除,但是可以调用drop()撒谎拿出集合中的所有行,但是drop后需要显式的重建集合,在32位机上,一个capped collection的最大值约为482.5m,64位机上只受系统文件大小的限制.

属性及用法:
属性1.固定集合插入速度极快.
属性2.插入顺序的查询输出极快.
属性3.能够在插入最新数据时,淘汰最早的数据.

用法1: 储存日志信息.
用法2: 缓存一些少量文档.
  • 创建固定集合
不像普通集合,固定集合需要显式的创建使用.
使用createCollection命令来创建.

db.createCollection('c1',{capped:true,size:10000,max:5});
创建一个固定集合,名为c1,大小10000,最大5个文档

注意:
	指定文档上限,必须指定大小.文档限制是在容量没有满时进行淘汰,如果满了,就要根据容量限制来进行淘汰
	
db.createCollection('集合名',capped:bool,size:num,max:num);
集合名: 建立集合的名称
capped: 建立一个固定集合
size:   最大文件多少
max:    最大文档个数
注意: 指定文档上线,必须指定大小.文档限制是在容量没满时进行淘汰.
要是满了,就根据容量限制来进行淘汰.

  • 转换普通集合为固定集合convertTocapped
转换为普通集合:
把普通集合转换为固定集合需要使用db.runCommand({convertTocapped:'c1',size:10000,max:5});
把c1普通集合转换为固定集合,大小为10000,

自然排序:
固定集合文档安排插入顺序存储的, 默认情况下查询就是按照插入顺序返回的.也可以使用$natural调整返回顺序.
db.c1.find().sort({'$natural':1});
1表示默认顺序,-1则相反.
判断使用: db.c1.isCapped();
状态使用: db.c1.stats();


db.runCommand({convertToCapped:'集合名',size:num,max:num});
集合名: 要转换为固定集合的普通集合名
size: 文件大小
max: 文档上限

GridFs大文件

  • GridFs讲解
GridFs是一种存储在MongoDB中的大的二进制文件的机制,使用GridFs的原因有:
1.存储巨大文件,如:视频,高清图片等,利用GridFs可以简化需求.
2.GridFs会直接利用已建立的复制和分片机制,故障回复和扩展都很容易.
3.GridFs可以避免用户上传内容的文件系统出现问题.
4.GridFs不产生磁盘碎片.

GridFS 用于存储和恢复那些超过16M(BSON文件限制)的文件(如:图片、音频、视频等)。
GridFS 也是文件存储的一种方式,但是它是存储在MonoDB的集合中。
GridFS 可以更好的存储大于16M的文件。
GridFS 会将大文件对象分割成多个小的chunk(文件片段),一般为256k/个,每个chunk将作为MongoDB的一个文档(document)被存储在chunks集合中。
GridFS 用两个集合来存储一个文件:fs.files与fs.chunks。
每个文件的实际内容被存在chunks(二进制数据)中,和文件有关的meta数据(filename,content_type,还有用户自定义的属性)将会被存在files集合中。
  • GridFs应用
GridFs使用两个表来存储数据:
files:  包含数据对象(存储基本属性:文件名称,上传时间,等)
chunks: 包含其他一些相关信息的二进制块(保存数据的真正文件内容).
为了使多个GridFs命名为一个单一的数据库,文件和块都有一个前缀,默认情况下,前缀是fs,所以任何默认的GridFs存储将包括命名空间fs.files和fs.chunks.
各种第三方语言可以更改其前缀.

添加文件
mongofiles put 文件名

下载文件
mongofiles get 文件名

查找文件名
mongofiles list 文件名

参数说明
-d 指定数据库,默认死 fs mongofiles list –d testGridfs

-u -p 指定用户名,密码

-h 指定主机

-port 指定主机端口

- -c 指定集合名,默认为 fs

-t 指定文件的 mime类型,默认会忽略.

索引&性能优化

  • 建立索引(普通索引)
建立索引的函数: ensureIndex()
例子:在 Name 上 建立索引 1(升序)-1(降序)

db.c1.ensureIndex({name:1});

当系统已经有大量数据时,创建索引会非常耗时,需要在后台执行.只需指定background:true即可

db.c1.ensureIndex({age:1},{background:true});

  • 唯一索引
只需要在 ensureIndex 命令中指定unique:true指定索引类型即可.
注意:
	如果集合中该字段,含有同样的两条数据,创建唯一索引将失败.
	
例如:
	db.c1.ensureIndex({name:1},{unique:true});
	创建 c1集合中 name 字段为唯一索引.
  • 查看索引
db.collection.getIndexKeys();
查看集合中的所有索引
例子:
db.c1.getIndexKeys();
查看 c1集合中的所有索引
  • 删除索引
dropIndexes();
删除所有索引
dropIndex({});
删除指定索引

主:
	_id 索引不能被删除

例子:
	db.c1.dropIndexes();
	删除c1集合中的所有索引
	
	db.c1.dropIndex({name:1});
	删除c1集合中name 字段的索引

性能优化

  • explain 执行计划
mongo提供了 一个 explain 命令让我们获知系统如何处理查询请求,利用 explain 命令我们可以很好的观察系统如何使用索引来加快搜索,同时有针对性的进行优化

db.c3.find({age:$gt:10},{name:1}).explain();

{
	'cursor':'BtreeCursor age_1', # 返回游标类型(BasicCuror 或 BtreeCursor)
	'nscanned': 0,	# 被扫描的文档数量
	'nscannedObjects':0,	
	'n':0,	# 返回的文档数量
	'millis':0,	# 耗时毫秒()
	'indexBounds':{	# 所使用的索引
					'age':[
						[
							45,
							1.7.97123123e+308
						]
					]
	}
}

MongoDB集合(collection)操作

注释:

当查询时同时使用sort,skip,limit,无论位置先后 最后执行顺序 sort再skip再limit。要不然截取的数据会乱.由结果可以得出,当sort,skip,limit一起使用时,无论其位置变化,总是先sort再skip,最后limit。


mongo中可以使用js语法:
    如: 
        insert测试数据时,一条一条的觉得很慢,可以使用js的for循环.
        for(i=0;i<10;i++){
        	db.c1.insert({name:'nihao'+i,sex:i});
        }
        
    如:
        findOne将查询的结果进行赋值再添加数据(find不能用,即使只find了一条也不能用)
        var x = db.c3.findOne({x:x});
        x.test1 = '测试1'
        x.test2 = '测试2'
        x(输出x得到之后复制的内容)
  • 增加(insert)
db.collection.insert({document});
db.collection.save({document});
    1.document: 为json格式的数据, 可以使用多层嵌套, 及其json中嵌套数组([]);
   
两者不同在于:
        insert插入时,主键相同报错,不同则插入.save插入时,主键相同修改数据, 不同则插入.
        
例子:
    查询出的结果:
    { "_id" : ObjectId("59128ebc330f067165b51d8f"), "name" : "liuhao" }
    { "_id" : '1', "name" : "zhangsan" }
    { "_id" : 1, "name" : "zhangsan" }
    在此处需要注意的是: 
        主键_ID是可以手动指定的.
        插入_id主键ID时,{_id:'1'}和{_id:1}是不一样的,但是{_id:'1'}等于{_id:"1"}
  • 保存(save)
集合的字段存在即修改不存在则删除

利用save和findOne({});利用save的_id存在则更新,不存在则插入的机制以及findOne({})查询的结果可以直接赋值成一个变量进行操作(变量内的值可以进行添加删除).可以实现非常厉害的功能.
即将查询出的一条数据进行修改,再写入集合.

如例:
var x = db.c3.findOne({name:'liuhao'});

x.sex = 1
x.age = 18
x.addr = '河南'
x.realName = '刘'
x.hobby = '波多野'

db.c3.save(x);
将name=liuhao的字段查询出同时赋值给一个变量.
通过变量的下标直接进行操作,添加个人信息.
利用save的存在即修改,来进行修改保存数据操作.

  • 删除(remove)
db.collection.remove({query},{justOne});   
删除该集合中的数据:
    query :(可选)删除的文档的条件。
    justOne : (可选)如果设为 true 或 1,则只删除一个文档
注意 如果不写条件, 则删除整个集合中的所有数据

db.collection.drop();
删除该集合

db.dropDatabase();
删除当前数据库,默认为 test,可以使用 db 命令查看当前数据库名。

  • 查询(find)
find批量查询
findOne查询一个(自带 游标)
db.collection.find({query},{projection}).pretty;     
如果不写条件则查询所有 相当于 MySql:select * 
    1.query: json格式的where条件
    2.projection: 可选的,从查询结果保留什么
    3.如果想以易读的方式展示使用.pretty()


例如:
    db.c1.find({sex:0},{name:0});
    查询sex=0的name字段不显示
   db.c2.find({'post.title':'a1','post.title':'b1'});
    查询json中嵌套数组,以数组内部值作为条件查询(post下数组中title=a1且title=b2).{ "_id" : ObjectId("5916a0ff0ca8e2abdb4689a6"), "name" : "user2", "post" : [ { "title" : "a1" }, { "title" : "b1" }, { "title" : "c1" } ] }


  • 修改(update)
db.collection.update();
  • 表达式
> 大于 - $gt
< 小于 - $lt
>= 大于等于 - $gte
<=  小于等于 - $lte
!=  不等于  -  $ne

查询中使用表达式:
    查询的条件一般在json内测
    如: sex > 0
        db.c1.find({sex:{$gt:0}});
        
    合在一起: 0 < sex < 10
    db.c1.find({sex:{$gt:0,$lt:10}});
        
    修改中使用表达式:
        修改的条件一般在json外侧


$or  或者:
    db.collection.find($or:[{age:1},{age:2}]); # 查询结果为age=1或者age=2的数据
    如:
        db.c1.find({$or:[{age:1},{age:2}]});
        
and 并且:
    db.collection.find({ke1:value1,key2:key2});
    mongo中并无,and操作符号,一般在查询时,以json格式写入的key,即为并且操作.需要注意的是: key1,key2应该是同一个字段的条件. 如果是两个字段则以第二个Key为准.
    如:
        db.c1.find({age:1,name:'liu1'}); # 正确写法,查询age=1且name='liu1'的字段
        db.c1.find({age:1,age:2}); # 错误的写法, 结果将age=2为标准作为查询

$in:[array] 在该数组中的
    db.collection.find({age:{$in:[1,2,3]}});
    查询age字段,其值在[1,2,3]中的结果
     $in和$all类似,但是in只要命中其中一个即可.
    如:
        db.c1.find({age:{$in:[1,2,3,4,5]}}); 
        查询age字段,其值在[1,2,3,4,5]中的结果
        
$nin:[array] 不在该数组中
    db.collection.find({age:{$nin:[1,2,3]}});
    不包含在[1,2,3]中的字段
    
    如:
        db.c1.find({age:{$nin:[1,2,3]}});
        查询,不包含在[1,2,3]该数组中的字段.

$mod:[array] 取模运算(数学上叫做取余)
    db.collection({age:{$mod:[2,0]}});
    匹配查询和2余0的字段.
    
$all:[array] 匹配数组中所有的值
    db.collection.find({age:{$all:[1,2,3]}});
    $all和$in类似,但是all需要匹配条件内所有的值
    
    如:
        db.c1.find({age:{$all:[1,2,3]}});
        匹配age字段同时该字段中,同时该字段必须含有这三个值.

$size 匹配数组长度
        db.collection.find({age:{$size:num}});
        值匹配数组长度为num的字段
        db.c1.find({age:{$size:3}});
        只匹配数组长度为3的字段

$exists:query 判断一个元素是否存在
        db.things.find({age:{$exists:true}}); 
        查询含有age的所有字段
        db.things.find({age:{$exists:false}}); 
        查询不存在age的所有字段

$not:query 取反
    db.collection.find({字段:{$not:{条件}}}});
    如:
        db.c1.find({age:{$not:{$mod:[2,0]}}});
        不匹配取余结果,和2取余为0的字段.
        db.c1.find({name:{$not:/liu*/}});
        不匹配正则匹配的内容

正则表达式
        db.collection.find({name:/string/});
        如:
            db.c1.find({name:/liu/});
            使用正则匹配姓刘的

  • 高级查询
count() 计算结果中的个数
        db.c1.count();  计算集合中文档的个数
        db.c1.find().count();   计算查询结果中文档的个数
        下面这个效率低,耗内存.

        
        
limit() 读取指定数量的数据记录
    db.collection.find().limit(10);从0开始读取10个
    但是该方法只有一个参数,不可以像MySQL中做分页时那样使用.
    要想自定义指定从N1获取到N2数据,需要skip()方法的辅助.
    如:
        db.c1.find().skip(10).limit(10); #跳过前十个,从第十个开始向后取十个
    
skip()  跳过指定数量的数据
    db.collection.find().skip(number).limit(number);
    如:
        db.c1.find().skip(0).limit(10); # 从第0个开始向后取10个
        db.c1.find().skip(10).limit(10); # 从第10个开始向后取10个
        
sort()  将查询结果进行排序
    db.collection.find().sort({key:1});
        key:1   升序
        key:-1  降序
    如:
        db.c1.find().sort({age:1}); # 升序排列
        db.c1.find().sort({age:-1}); # 降序排列
        
$elemMatch 匹配查询
    db.collection.find({x:{$elemMatch:{a:1}}});
    匹配json对象(x)中数组内json下标a为1的
    例如:
          db.c2.find({x:{$elemMatch:{a:1,b:{$gt:1}}}});
          查询c2集合中json对象x下数组内json对象的下标为a=1的且b>1的字段
          db.c2.find({post:{$elemMatch:{title:'a1',title:'b1'}}});
          结果:
            { "_id" : ObjectId("5916a0ff0ca8e2abdb4689a6"), "name" : "user2", "post" : [ { "title" : "a1" }, { "title" : "b1" }, { "title" : "c1" } ] }
    
Null查询
    Null: 值为Null, 字段不存在.
    db.collection.find({x:null});
    查询该值为Null的字段
    
    如果本意是想查询该字段的某个值为Null类型时,其他字段中不存在该值的也会认为是Null.所以在使用中为区分开, 我们需要做判断.
    
    db.c3.find({sex:{$exists:1,$in:[null]}});
    查询sex字段存在,同时其值确实亲为Null.
    或者使用$type
    db.c3.find({$type:10},name:'liu');
    查询数据类型为10(Null),同时名称为liu的数据.
  
$selice 剪取
     db.collection.find({},{x:{$slice:[a,b]}});
    从查询结果中剪切数据,从a-b(从0开始可以只写第二个值,可以为负数)
    
    db.c2.find({post:{title:1}},{post:{$slice:[0,4]}});
    查询,post下的数组下标为title的值为1的字段,并剪切post下的数组, 从0-4
    
    db.c2.find({},{post:{$slice:1}});
    查询所有数据, 将post字段下的数组剪切0-1
    
  • 聚合操作
distinct() 取唯一值,键值去重
    db.collection.distinct('name')
    
    db.c1.distinct('name');
    查看c1集合中name列的所有唯一的字段



  • 游标 cursors及cursor Methods
一般数据库要么一次性把数据都读出来, 要么以游标的形式,连接数据库一行一行的根据需求拿取数据,断开数据.
为了避免,一次性把符合需求的数据全部拿出来, 有用游标是一个不错的方法.

var x = db.collection.find({});
将查询结果复制在x中.不会直接输出

x.hasNext();
判断x中是否有下一个值true为有,false为空

x.next();
输出一行查询出的内容,查询到无结果时会报错.

高级更改操作

  • update 高级
    db.collection.update( criteria, objNew, upsert, multi )
    
参数说明:
Criteria:用于设置查询条件的对象
Objnew:用于设置更新内容的对象
Upsert:如果记录已经存在,更新它,否则新增一个记录(默认0)需要指定魔术变量(如:$set,$inc)才能用
Multi:如果有多个符合条件的记录,全部更新(默认0)
注意:默认情况下,只会更新第一个符合条件的记录,如果直接修改的话, 会变成一个新的对象.之前的内容被替换为修改的内容, 之前的内容不存在.
如:
   b.c1.update({name:'liu0'},{age:111});
   原来的字段变成age:111,其他内容消失.
   
如果想只修改一个字段中的一个值,需要使用魔术变量$set
如:
    db.c3.update({name:'liu4'},{$set:{age:'10'}});
    
  • $inc 递增
db.collection.update({x:x},{$inc:{x:x}},0,1);
可使用减号,匹配某字段中的某个值自增多少(必须为整型).(update第四个值为true,修改符合要求所有字段)
如果该字段没有, 则添加字段,赋值然后自增.null值不可自增.

> db.c3.update({name:/liu/},{$inc:{age:10}},0,1);
正则匹配liu的字段中age字段全部加10

$set和$inc的区别:

都可以添加字段,$set可以直接改掉.但是$inc在原来的值上可以加减(必须为整型.)
  • $unset 删除指定字段的field
db.collection.update({x:x},{$unset:{x:x}});
删除x匹配字段中的x的field(不能删除_id)

db.c3.update({name:'liu'},{$unset:{sex:10}});
删除字段name=liu中sex为10的field

db.c3.update({},{$unset:{sex:21}},0,1);
删除该合集中,所有sex=21字段中的sex域

  • $push&$pushAll 在数组的最后添加一个字段
$push推入一个值
$pushALl推入一个数组
可推入重复值


  • $addToSet 也是在数组的最后推入一个值
不可推入重复值


如果要一次性推入多个值需要和$each配合使用


  • $pop删除数组中的最后一个元素
db.collection.update({x,x},{$pop:{x:bool}});
bool为1时删除最后一个
bool为-1时删除第一个
  • $pull&$pullAll 如果数组中的值存在则删除,不存在则报错
$pull 匹配一个值
$pullAll匹配一个数组
db.collection.update({x:x},{$pull:{x:1}});
删除符合该条件的字段中的x数组中的该值(如果该值存在则删除,不存在则报错).




  • $rename重命名该字段

  • 特殊操作符 $
$操作符代表查询记录中第一个匹配条件的记录项。



MongoDB数据库管理

  • 注意
据称读写分离, 主服务器重启之后,子服务器会重新从主服务器读取数据,同时清空本服务器数据.
所以要做好备份.
v3.4.4亲测
测试使用停掉子服务器,删除主服务器内容重写其他内容.结果,数据库连接后,子服务器内容,同步.

数据导出&数据导入&数据备份&数据回复

  • 数据导入导出
数据导出:
    mongoexport
    命令行用于数据的导出,默认导出的文件格式为JSON格式。当然也可以指定特定的文件格式。
    
    ./mongoexport --help 查看帮助
    
    参数:
        -h:数据库宿主机的IP
        -u:数据库用户名
        -p:数据库密码
        -d:数据库名字
        -c:集合的名字
        -f:导出的列名
        -q:导出数据的过滤条件
        --csv:导出格式为csv(version v3.4.4需要使用--type=csv 同时,在-f 中指定导出的字段)
    注意:
        csv 格式,不导出UID.
        
    具体操作:
        ./mongoexport -d test -c c1 -o c1.dat
        导出该 c1集合中所有的数据,默认为 json 格式.
        ./mongoexport -d test -c c1 --type=csv -f name,age -o c1.dat
        导出 c1集合中 name以及age 字段的数据,格式为 csv 格式.
        
    
数据导入:
    mongoexport
    
    具体操作:
        mongoimport -d test -c c1 c1.bat
        将 c1.bat 文件导入到 test 数据库下的 c1集合中
        
    注意:
        json 格式导入时,会自动隐式创建数据结构.
        
数据备份:
    mongodump
    
    具体操作:
        ./mongodump -d test -o ./testDb
    备份整个 test 数据库到 当前目录下 testDb 文件.(不实用-o 指定路径,默认到 bin 下的 dump 目录下,使用 port 指定端口号 mongodump --port=27020)
    
数据恢复:
    mongorestore
    
    具体操作:
         sudo mongorestore -d test ./testDb/*
         导入 当前目录./testDb 下的所有数据到 test 数据库中.
    
    注意:
        恢复数据需要使用root 用户
        使用-drop 参数可以导入的同时,删除之前的内容.
        如下:
            sudo mongorestore -d test -drop ./testDb/*
    

安全与认证

  • 用户授权
每个 MongoDB实例中的数据库都有许多用户,
如果启用了安全性认证后,只有数据库认证的用户才可以进行读写操作.
MongoDB默认启动是不验证用户名和密码,启动 MongoDB后可以直接使用 mongo连接上来,
对所有数据库,都具有root 权限.所以启动的时候指定参数,可以阻止客户端的连接和访问.
只需要在启动时指定 --auth 参数即可.此时数据库当会多一个 admin 库.

修改配置开启动用户权限认证:
    vim /etc/mongodb.conf      //将auth=true前面的注释拿掉
    /etc/init.d/mongod restart   //重启生效

例如:
    我在Mac 中的启动方式
    mongod --dbpath=/usr/local/Cellar/mongodb/3.4.4/data/ --logpath=/usr/local/Cellar/mongodb/3.4.4/log/log --auth

    此时,用户如果没有数据库权限, 则连接之后,没有任何权限.
  • 用户授权
添加用户
mongo V3.0后使用db.createUser()创建用户;

如下:

> db.createUser(
...   {
...     user: "dba",
...     pwd: "dba",
...     roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
...   }
... )

ser:用户名

pwd:密码

roles:指定用户的角色,可以用一个空数组给新用户设定空角色;在roles字段,可以指定内置角色和用户定义的角色。role里的角色可以选:
Built-In Roles(内置角色):
    1. 数据库用户角色:read、readWrite;
    2. 数据库管理角色:dbAdmin、dbOwner、userAdmin;
    3. 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
    4. 备份恢复角色:backup、restore;
    5. 所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
    6. 超级用户角色:root  
    // 这里还有几个角色间接或直接提供了系统超级用户的访问(dbOwner 、userAdmin、userAdminAnyDatabase)
    7. 内部角色:__system
    
Read:允许用户读取指定数据库
readWrite:允许用户读写指定数据库
dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
userAdmin:允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户
clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。
readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。
root:只在admin数据库中可用。超级账号,超级权限


有没有一个超级权限?不仅可以授权,而且也可以对集合进行任意操作?答案是肯定的,只是不建议使用。那就是role角色设置成root。

> db.createUser(
...  {
...    user: "zhoujinyi",
...    pwd: "zhoujinyi",
...    roles: [
...       { role: "root", db: "admin" }      #超级root帐号
...    ]
...  }
... )


创建了这么多帐号,怎么查看所有帐号?
 db.system.users.find().pretty()
 
 现在需要创建一个帐号,该账号需要有grant权限,即:账号管理的授权权限。注意一点,帐号是跟着库走的,所以在指定库里授权,必须也在指定库里验证(auth)。


 > use admin
switched to db admin
> db.createUser(
...   {
...     user: "dba",
...     pwd: "dba",
...     roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
...   }
... )

  • 使用密码连接数据库


  • 权限管理解释
在最初始化的时候 MongoDB都默认有一个admin 数据库,(默认是空的)admin.system.users中将会是保存具有管理员权限的用户.

注意:
    当 admin.system.users中没有添加任何用户时,即使MongoDB启动时添加--auth参数,如果在除admin数据库中添加了用户,此时不进行任何认证,依然有使用任何操作,直到你在 admin.system.users中添加了一个用户.

性能优化

  • explain执行计划
MongoDB提供了一个explain命令让我们获知系统如何处理,查询请求.利用 explain 命令我们可以很好的观察系统如何使用索引来加快检索,同时可以针对优化检索.

explain 使用案例:
    db.c1.find().explain();
    
  • 优化器profile
MongoDB Database Profile 是一种慢查询日志功能,可以作为我们优化数据库的依据.
开启 Profile功能
有两种方式可以控制Profile开关和级别.
启动MongoDB时加上-profile=级别即可
在客户端调用 db.setProfilingLevel(级别)命令来实时配置,
Profile信息保存在system.profile该.我们可以通过db.getProfilingLevel()命令来获取当前的 Profile级别.
db.getProfilingStatus()获取当前慢查询状态设置.

具体操作:
    db.setProfilingLevel(2); #设置慢操作级别和慢时间定义,单位毫秒(默认100ms)  
    db.getProfilingLevel();  #查看跟踪级别
    db.getProfilingStatus(); #查看当前设置 
    
    上面的profile的级别可以取0,1,2三个值,他们分别表示:
    0 _ 不开启
    1 _ 记录慢查询(默认>100MS)
    2 _ 记录所有命令

注解:
    Profile 在级别1时会记录慢命令,上面的默认值为100MS, 有默认就有设置,其设置方法和级别有两种方法:
        一种是通过添加--slows 启动参数设置.
        如: --slows=10(单位毫秒)
        
        另一种是db.setProfilingLevel()时加上第二个参数.
        
        db.setProfilingLevel(1,10);
        设置慢操作级别和慢时间定义,单位毫秒(默认100ms) 
        
        那么这么慢的定义是什么?
        可以理解比较耗时的命令,
        如一个查询耗时10毫秒就会被记录下来.
        
        

数据库监控

Mongosniff
    此工具可以从底层监控到底有哪些命令发送给MongoDB去执行.
    ./mongosniff --source NET lo
    他是实时动态监控的,需要打开另一个客户端进行命令操作,可以将这些数据输出到一个日志文件中,那么就可以保存下来所有数据库操作的历史纪录.对于后期的性能分析和安全审计等工作将是一个巨大贡献.
    å


 mongostat
    使用mongo 目录下的该文件,进行监控 mongo.
    下面是 执行结果(不分)
    
    
    
mongotop
    使用 mongo 目录下的该文件, 用来跟踪一个MongoDB的实例,查看哪些大量的时间花费在读取和写入数据。 
 

主从复制&副本集.

  • 主从复制 Master-Slave复制(主从)
只需要在某一个服务器启动时加上--master参数,而另一个加上--slave与--source参数,即可实现同步.
MongoDB的最新版,已经不推荐使用这种方式了.

具体操作:
    ./mongod --master --dbpath=/usr/local/Cellar/mongodb/3.4.4/data/ --logpath=/usr/local/Cellar/mongodb/3.4.4/log/log --port=2001 --fork
    主服务器配置
    
    ./mongod --slave --source 127.0.0.1:2001 --dbpath=/usr/local/Cellar/mongodb/3.4.4/data2/ --logpath=/usr/local/Cellar/mongodb/3.4.4/log2/log --port 2002 --fork
    从服务器配置
    
注释:
    从服务器,进入后,show dbs;如果报出错误内容:	"errmsg" :"not master and slaveOk=false","code" : 13435,"codeName" : "NotMasterNoSlaveOk"
    使用rs.slaveOk(); 之后即可正常操作.原因:从服务器上的数据库是不允许进行读写操作,所以就会报类似于这样的错误,这句是解决方法。
    暂未尝试在设置安全验证的服务器中使用 rs.slaveOk();实验其可不可以用.
        
其它一些配置项: 
    only  从节点---》 指定复制某个数据库,默认是复制全部数据库
    slavedelay  从节点---》设置主数据库同步数据的延迟(单位是秒)
    fastsync 从节点---》以主数据库的节点快照为节点启动从数据库
    autoresync 从节点---》如果不同步则从新同步数据库
    oplogSize  主节点---》设置oplog的大小(主节点操作记录存储到local的oplog中)
    
备注:
    主从备份中,主服务器是可以增加用户的,但是从服务器上不允许增加用户,会报下面的错。
    此点还没有详细看是不允许增加所有用户,还是不允许增加超级用户,暂时先不做研究
    据称读写分离, 主服务器重启之后,子服务器会重新从主服务器读取数据,同时清空本服务器数据.
    所以要做好备份.
    v3.4.4亲测
    测试使用停掉子服务器,删除主服务器内容重写其他内容.结果,数据库连接后,子服务器内容,同步.

Replica Sets 复制(副本集)

  • 了解副本集
MongoDB 在1.6版本开发了 replica set,主要增加了故障自动切换和自动修复成员节点,各个 DB 之间数据完全一致,最为显著的区别在于,副本集没有固定的注解点,他是整个集群选举出的一个注解点,在其不工作时变更其他节点,强烈推荐使用.

注意点:
	- 服务器节点之前时间要同步
	- 开启防火墙的一定要允许通过
	- 开启selinux的也要进行设置
	- 建立双击互信模式最好不过
  • 部署 Replica Sets 副本集
启动两个实例:
	1.创建数据文件存储路径
	mkdir -p /data/data/r0
	mkdir -p /data/data/r1
	2.创建日志文件路径
	mkdir -p /data/log
	3.创建主从 key 文件用于标识集群的私钥的完整路径,如果各个实例的 key file 内容不一致,程序将不能正常使用.
	mkdir -p /data/key
	echo 'this is key' > /data/key/r0
	echo 'this is key' > /data/key/r1
	chmod 600 /data/key/r*
	4.启动两个实例
	./mongod --replSet rsl --keyFile /data/key/r0 --fork --port 2001 --dbpath /data/data/r0 --logpath=/data/log/r0.log --logappend
	
	./mongod --replSet rsl --keyFile /data/key/r1 --fork --port 28011 --dbpath /data/data/r1 --logpath=/data/log/r1.log --logappend
	
	--replSet rsl 副本集的名字

转载于:https://my.oschina.net/chinaliuhan/blog/3065360

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值