一、MongoDB数据库简介
MongoDB,是NoSQL数据库,是一个基于分布式文档存储的开源数据库系统,旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB 将数据存储为一个文档,数据结构由键值对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
二、MongoDB数据库对比MySQL数据库的概念
MySQL数据库概念 | MongoDB数据库概念 | 解释 |
---|---|---|
database | database | 数据库 |
table | collection | 前者:数据库表,后者:集合 |
row | document | 前者:行,后者:文档 |
column | field | 前者:列,后者:域 |
index | index | 索引 |
table joins | 前者:表连接,后者:不支持 | |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
三、MongoDB数据库的库和集合操作
3.1 查看数据库列表
show dbs;
3.2 创建数据库
use testdb;
这时,使用
show dbs;
并没有看到创建的testdb
数据库,但通过返回的switched to db testdb
,说明已经切换到创建的数据库了,这是由于MongoDB是隐式创建数据库,当使用use 数据库名称
时,就已经创建数据库了。
想要通过
show dbs;
,显式的查看创建出的数据库,则需要在创建的数据库下创建表。
3.3 删除数据库
db.dropDatabase();
删除当前所在的数据库。
3.4 创建集合
db.createCollection("user");
当使用
db.createCollection("集合名");
命令创建集合之后,再使用show dbs;
命令查看数据库,则可以看到数据库也显示出来了。
3.5 查看集合列表
show collections;
3.6 删除集合
db.user.drop();
使用
db.表名.drop();
命令,删除指定集合。
四、MongoDB数据库增删改查的基本使用
4.1 增操作----insert
Mongodb存储的是文档,文档是json格式的对象。
(1)插入一条数据
db.user.insert({name:'qianye',age:25,programe:'java'});
通过
db.user.find();
命令,可以查user集合里的所有数据,可以看到除了插入的数据,MongoDB数据库自动随机生成_id
。
当然也可以自己指定
_id
值,例如:
db.user.insert({_id:1,name:'xiaoyi',age:24,programe:'java'});
(2)插入多条数据
db.user.insert([{_id:2,name:'xiaoer',age:27,programe:'php'},{_id:3,name:'xiaosan',age:27,programe:'go'},{_id:4,name:'xiaosi',age:28,programe:'c'}]);
(3)定义变量插入数据
可以将需要插入的数据,定义成一个变量,然后执行
db.集合名.insert(变量名);
。
document=({_id:5,name:'xiaowu',age:25,programe:'c++'});
db.user.insert(document);
4.2 删操作----remove
(1)删除一条数据
db.user.remove({name:'qianye'},true);
或者
db.user.remove({name:'qianye'},1);
删除操作,第二个可选参数指定为true或指定为1时,会将文档中包含指定条件的第一条数据删除。即使有多个包含指定条件的数据,也只会删除第一条数据。
(2)删除多条数据
db.user.remove({name:'qianye'});
或者
db.user.remove({name:'qianye'},0);
删除操作,第二个可选参数不选或指定为0时,会将文档中包含指定条件的数据都删除。
(3)删除当前collection下所有文档
db.user.remove({});
4.3 改操作----update
db.集合名.update(查询表达式,新值,可选参数选项);
(1)替换文档操作
db.user.update({name:'xiaoyi'},{name:'xiaoliu'});
注意:这是新文档替换了旧文档
(2)指定修改
使用
$set
操作符,用指定的值替换字段的值。
db.user.update({name:'xiaoyi'},{$set:{age:25}});
(3)删除特定字段
使用
$unset
操作符,删除特定字段。
db.user.update({name:'xiaoliu'},{$unset:{test:1}});
(4)更新字段名
使用
$rename
操作符,更新字段名。
db.user.update({name:'xiaoqi'},{$rename:{year:'age'}});
(5)字段递增指定的值
使用
$inc
操作符,将字段递增指定的值。
db.user.update({name:'xiaoqi'},{$inc:{age:2}});
(6)当发生update修改操作并有insert插入操作时,进行补充字段操作。
如果
upsert: true
的update
操作导致插入文档,那么$setOnInsert
将指定的值分配给文档中的字段。如果更新操作没有导致插入,则$setOnInsert
不执行任何操作。
db.user.update({name:'xiaoba'},{$set:{name:'xiaojiu'},$setOnInsert:{age:24,programe:'go'}},{upsert:true});
对于
upsert:true
可选项,是当修改操作指定时,如果没有匹配的行,则直接插入该行(true或者1)。
db.user.update({name:'xiaoba'},{$set:{name:'xiaoshi'}},{upsert:true});
(7)更新多个文档
可选项,如果
multi
设置为true
, 将更新满足查询条件标准的所有文档。
db.user.update({age:27},{$set:{age:26}},{multi:true});
4.4 查操作----find
(1)查询所有文档
db.user.find();
(2)查询有多少文档
db.user.find().count();
(3)查询所有文档的某个字段
db.user.find({},{name:1});
默认会将
_id
字段查询出来
(4)查询所有文档age字段为26的name字段且不带_id属性
db.user.find({age:26},{name:1,_id:0});
(5)查询所有文档age字段不等于26的,且只显示age字段,name字段,不显示_id字段
$ne
选择字段值不等于指定值的文档。这包括不包含字段的文档。
db.user.find({age:{$ne:26}},{age:1,name:1,_id:0});
(6)查询所有文档age字段大于26的,且只显示age字段,name字段,不显示_id字段
$gt
选择字段值大于(即>)指定值的文档。
db.user.find({age:{$gt:26}},{age:1,name:1,_id:0});
(7)查询所有文档age字段大于等于26的,且只显示age字段,name字段,不显示_id字段
$gte
选择字段值大于或等于指定值(例如,>=)的文档。
db.user.find({age:{$gte:26}},{age:1,name:1,_id:0});
(8)查询所有文档age字段小于26的,且只显示age字段,name字段,不显示_id字段
$lt
选择字段值小于(即<)指定值的文档。
db.user.find({age:{$lt:26}},{age:1,name:1,_id:0});
(9)查询所有文档age字段小于等于26的,且只显示age字段,name字段,不显示_id字段
$lte
选择字段值小于或等于(即<=)指定值的文档。
db.user.find({age:{$lte:26}},{age:1,name:1,_id:0});
(10)查询文档age字段大于等于25 且 小于等于28的,且只显示name字段,age字段,不显示_id字段
$and
对包含两个或多个表达式的数组执行逻辑和操作(例如<表达式1>
,<表达式2>
,等等),并选择满足数组中所有表达式的文档。$and
操作符使用短路评估。如果第一个表达式(例如<表达式1>
)的值为false
, MongoDB将不计算其余表达式的值。
db.user.find({$and:[{age:{$gte:25}},{age:{$lte:28}}]},{name:1,age:1,_id:0});
(11)查询文档age字段大于等于25 或 小于等于28的,且只显示name字段,age字段,不显示_id字段
$or
操作符对两个或多个<表达式>
组成的数组执行逻辑或操作,并选择满足至少一个<表达式>
的文档。
db.user.find({$or:[{age:{$gte:25}},{age:{$lte:28}}]},{name:1,age:1,_id:0});
(12)查询文档age字段包含24和26的,且只显示name字段,age字段,不显示是_id字段
$in
操作符选择字段的值等于指定数组中的任何值的文档。
db.user.find({age:{$in:[24,26]}},{name:1,age:1,_id:0});
(13)查询文档age字段不包含24和26的,且只显示name字段,age字段,不显示是_id字段
$nin
选择以下文档:字段值不在指定数组中或字段不存在。
db.user.find({age:{$nin:[24,26]}},{name:1,age:1,_id:0});
(14)查询文档age字段不包含24和26的,且只显示name字段,age字段,不显示是_id字段
$nor
对一个或多个查询表达式的数组执行逻辑或操作,并选择数组中所有查询表达式都失败的文档。
db.user.find({$nor:[{age:24},{age:26}]},{name:1,age:1,_id:0});
(15)查询文档age字段除以5余数为0的,且只显示name字段,age字段,不显示_id字段
$mod
求余,选择一个字段除以一个除数的值有指定余数的文档(即执行一个模数操作来选择文档)。
db.user.find({$nor:[{age:24},{age:26}]},{name:1,age:1,_id:0});
(16)查询文档含有age字段值的
当
<boolean>
为true
时,$exists
匹配包含该字段的文档,包括字段值为null
的文档。如果<boolean>
为false
,则查询只返回不包含该字段的文档。
db.user.find({age:{$exists:true}});
(17)查询文档age的值是Double类型的
$type
选择字段值为指定BSON类型实例的文档。在处理数据类型不可预测的高度非结构化数据时,按数据类型查询非常有用。
db.user.find({age:{$type:1}});
常见的类型所对应的数值
(18)查询文档age大于25的
使用
$where
操作符将包含JavaScript表达式的字符串或完整的JavaScript函数传递给查询系统。$where
提供了更大的灵活性,但要求数据库处理集合中每个文档的JavaScript表达式或函数。使用this或obj在JavaScript表达式或函数中引用文档。
db.user.find({$where:'this.age>25'});
注意:当由where操作时,会将逐一遍历mongo集合中文档对象,将其属性由Bson格式转换为Json。然后能通过json找到对象属性,供js来调用,
查询效率会比较低
。但能写出比较复杂的操作语句,能使的表达式写的比较容易。
(19)子文档查询
db.user.find({'spc.area':'taiwan'});
五、MongoDB数据库的游标操作
5.1 什么是游标----cursor
游标不是查询结果,可以理解为数据在遍历过程中的内部指针,其返回的是一个资源,或者说数据读取接口。
5.2 游标的基本使用
(1)声明游标
var cursor = db.user.find({_id:{$gt:4}});
(2)判断游标是否已经取到尽头
cursor.hasNext();
(3)取出游标的下1个单元(从0开始游)
cursor.next();
5.3 使用while循环游标
var cursor = db.user.find({_id:{$gt:4}});
while (cursor.hasNext()) {
printjson(cursor.next());
};
注意:print打印的是二进制对象,printjson打印出来的才是可阅读的json格式数据。
5.4 使用forEach循环游标
var cursor = db.user.find({_id:{$gt:4}});
cursor.forEach(function(obj){printjson(obj)});
obj
就是查出的文档对象
取出_id的值:
var cursor = db.user.find({_id:{$gt:4}});
cursor.forEach(function(obj){printjson(obj._id)});
5.5 游标在分页中的使用
(1)查询结果,跳过前100行
var cursor = db.user.find().skip(100);
cursor.forEach(function(obj){printjson(obj)});
(2)查询第11页,每页5条数据
var cursor = db.user.find().skip(50).limit(5);
cursor.forEach(function(obj){printjson(obj)});
如果不使用游标:
(3)查询第11页,每页5条,第二行的数据
var cursor = db.user.find().skip(50).limit(5);
printjson(cursor.toArray()[2]);
printjson(cursor.toArray()); ---- 看到所有行
注意:不要随意使用toArray()
原因:会把所有的行立即以对象形式组织在内存里。可以在取出少数几行时,用此功能。
六、MongoDB数据库索引的使用
6.1 查看查询计划
db.user.find({age:4}).explain();
6.2 添加索引
(1)在name字段上,添加索引
db.user.ensureIndex({name:1});
这里的1表示索引创建的方向,可以取值为1和-1。
(2)添加多列索引
db.user.ensureIndex({'name':1,'age':1});
(3)添加唯一索引
db.user.ensureIndex({'name':1},{unique:true});
(4)添加子文档索引
db.user.ensureIndex({'spc.area':1});
6.3 查看索引
db.user.getIndexes();
6.4 删除索引
(1)删除指定的索引
db.user.dropIndex({'name':1});
(2)删除所有的索引
db.user.dropIndexes();