MongoDB的使用
一、MongoDB简介
- MongoDB是为快速开发互联网web应用而设计的数据库系统。
- MongoDB的设计目标是极简、灵活、作为web应用栈的一部分。
- MongoDB的数据模型是面向文档的,所谓文档是一种类似于JSON的结构,简单理解MongoDB这个数据库中存得是各种各样得JSON。(BSON增强版的json)。
二、MongoDB三个概念
- 数据库(database):数据库是一个仓库,在仓库中可以存放集合。
- 集合 (collection):集合类似于数组,在集合中可以存放文档。
- 文档 (document):文档数据库中的最小单位,我们存储和操作的内容都是文档。
在MongoDB中,数据库和集合豆豆不需要手动创建,当我们创建文档时,如果文档所在的集合或数据库不存在会自动创建数据库和集合。
三、Windows安装MongoDB
参考自己的博文:https://www.cnblogs.com/nastu/p/16271881.html
四、操作Mongo数据库
基本的指令:
#显示当前的所有数据库
show dbs
show databases
#进入到指定的数据库中
use 数据库名
#表示当前所处于哪个数据库
db
#查看数据库里面所有的集合
show collections
数据库的增删改查(CURD)
#向数据库中插入文档
db.<集合名称>.insert(doc)
#向集合中插入一个文档
#例如,向test数据库中的stus集合中插入一个新的学生对象
{name:"孙悟空",age:18,gender:"男"}
#输入以下命令
db.stus.insert({name:"xia",age:22,gender:"male"});
查找集合的文档内容
db.stus.find()
五、安装MongoDB图形化工具【有很多中工具(Studio 3T)选择适合自己的即可】
下载地址:https://www.mongodbmanager.com/download-mongodb-manager-free
下载之后傻瓜式的安装即可,连接MongoDB数据库
注意:如果遇到无法输入中文直接退出重启一下就可以了。
六、数据库操作
1、插入文档
/*向集合中插入1个文档*/
db.stus.insert({name:"夏天",age:18,gender:"男"});
/*向集合中插入多个文档*/
db.stus.insert([
{name:"小一",age:22,gender:"男"},
{name:"小二",age:22,gender:"女"},
{name:"小三",age:22,gender:"女"}
]);
db.stus.find();
/*生成ID码*/
ObjectId()
/*自定义ID*/
db.stus.insert({_id:"hello",name:"夏天",age:18,gender:"男"});
db.集合名称.insertOne() #插入一个文档,里面不能有数组
db.集合名称.insertMany() #插入多个文档,里面必须是数组
2、查询文档
/*
查询
db.collection.find()
- find()用来查询集合中所有符合条件的文档
- find()可以接收一个对象作为条件参数
{} 表示查询集合中所有的文档
{属性名:值} 查询属性是指定值的文档
- find()返回的是一个数组
db.collection.findOne()
- 用来查询集合中符合条件的第一个文档
- findOne()返回的是一个文档对象
db.collection.find({}).count()
- 查询所有结果的数量
*/
/*查询指定条件的文档,id是hello的文档*/
db.stus.find({_id:"hello"});
/*查询指定条件的文档,age是22,name是小三*/
db.stus.find({age:22,name:"小三"});
/*查询指定条件的文档,age是22,查询数组索引为1的文档*/
db.stus.find({age:22})[1];
/*查询指定条件的文档,age是22,返回的是一个对象*/
db.stus.findOne({age:22});
/*查询所有结果的总数*/
db.stus.find({}).count();
3、修改文档
/*
修改
db.collection.update(查询条件、新对象)
- update()默认情况下会使用新对象来替换旧的对象
- 如果需要修改指定的属性,而不是替换需要使用"修改操作符"来完成修改
$set 可以用来修改文档中的指定属性
$unset 删除文档中指定的属性
- update 默认情况只会修改一个
db.collection.updateMany()
- 同时修改多个符合条件的文档
db.collection.updateOne()
- 修改一个符合条件的文档
db.collection.replaceOne()
- 替换一个文档
*/
//查询结果
db.stus.find({});
//替换掉所有的内容,仅剩下age信息
db.stus.update({name:"小三"},{age:1});
//替换指定的某一个或多个内容
db.stus.update(
{"name":"夏天"},
{$set:{
name:"Hello"
}}
);
//删除文档中指定的一个或多个属性,删除gender属性
db.stus.update(
{"name":"夏天"},
{$unset:{
gender:"男"
}}
);
//目前小一存在两个,使用updateMany将同时修改两个文档,将其address修改为香港
db.stus.updateMany(
{"name":"小一"},
{
$set:{
address:"香港"
}
}
);
//查询结果
db.stus.find();
//小一有多个的情况下只修改一个
db.stus.updateOne(
{"name":"小一"},
{
$set:{
address:"香港九龙"
}
}
);
//multi:true,也是表示小一有多个的情况下,同时修改多个
db.stus.update(
{"name":"小一"},
{
$set:{
address:"香港平顶山"
}
},
{
multi:true
}
);
4、删除文档
/*
删除
db.collection.remove()
- 删除符合条件的所有的文档(默认情况下会删除多个)
如果remove()第二个参数传递一个true,则只会删除一个
如果传递空对象则删除所有
db.collection.deleteOne()
db.collection.deleteMany()
- remove()可以根据条件来删除文档,传递的条件的方式和find()一样
db.collection.drop()删除集合
db.dropDatabase()删除数据库
-一般数据库中的数据都不会删除,所以删除的方法很少调用
*/
db.stus.find();
db.stus.remove({_id:"hello"});
//删除name为小一的文档(删除多个)
db.stus.remove({name:"小一"});
//删除name为小二的文档(只删除1个)
db.stus.remove({name:"小二"},true);
//传递空对象则删除所有的文档【清空集合,一个一个删除(性能略差)】
db.stus.remove({});
//清空集合(性能高)
db.stus.drop();
七、练习1
1、进去my_test数据库
show dbs
use my_test
db
2、向数据库的user集合中插入一个文档
db.user.insert({name:"夏天",age:"12",gender:"女"});
3、查询user集合中的文档
show collections
db.user.find();
4、向数据库的user集合中插入一个文档
db.user.insert({name:"春天",age:"14",gender:"女"});
5、查询数据库user集合中的文档
db.user.find();
6、查询数据库user集合中的文档数量
db.user.find().count();
7、查询数据库user集合中name为"春天"的文档
db.user.find({name:"春天"});
8、向数据库user集合中的name为"春天"的文档,添加一个address属性,属性值为"香港"
db.user.update(
{name:"春天"},
{$set:{address:"香港"}}
);
9、使用{name:"春天"} 替换 name 为 "张三" 的文档
db.user.update(
{name:"春天"},
{$set:{name:"张三"}}
);
10、删除 name 为 张三 的文档的address属性
db.user.update(
{name:"张三"},
{$set:{address:"广州"}}
);
11、向name为夏天的文档中,添加一个hobby:{cities:["beijing","shanghai","shenzhen"], movies:["sanguo","hero"]}
db.user.update(
{name:"夏天"},
{$set:{hobby:{cities:["beijing","shanghai","shenzhen"], movies:["sanguo","hero"]}}}
);
12、向name为张三的文档中,添加一个hobby:{movies:["A Chinese Odyssey","King of comedy"]}
db.user.update(
{name:"张三"},
{$set:{hobby:{movies:["A Chinese Odyssey","King of comedy"]}}}
);
13、查询喜欢的电影hero的文档
MongoDB支持直接通过内嵌文档的属性进行查询,如果要查询内嵌文档则可以通过.的形式匹配
如果要通过内嵌文档来对文档进行查询,此时属性名必须使用引号,对数组或元素进行匹配
db.user.find({'hobby.movies':"hero"});
14、向张三中添加一个新的电影Interstellar
$push 用于向数组中添加一个新的元素
$addToSet 向数组中添加一个新元素,如果数组中已经存在该元素则不会重复添加
db.user.update(
{name:"张三"},
{$push:{"hobby.movies":"Interstellar"}}
);
db.user.update(
{name:"张三"},
{$addToSet:{"hobby.movies":"Interstellar"}}
);
15、删除喜欢beijing的用户,(删除cities里面包含beijing的用户)
db.user.remove({"hobby.cities":"beijing"});
16、删除user集合
db.user.remove({});
db.user.drop();
show dbs;
17、向numbers中插入2000条数据,使用for循环
for(var i=1; i<=20000; i++){
db.numbers.insert({num:i});
}
#以上方式效率太低了,每循环一次得insert一次
优化方案:尽量在调取方法之前讲数据处理完再一次性插入数据
var arr = [];
for(var i=1; i<=20000; i++){
arr.push({num:i});
}
db.numbers.insert(arr);
18、查询numbers中num为500的文档
db.numbers.find({num:500});
19、查询numbers中num大于5000的文档
db.numbers.find({num:{$gt:5000}});
//大于等于5000的文档
db.numbers.find({num:{$gte:5000}});
20、查询numbers中num小于30的文档
db.numbers.find({num:{$lt:30}});
db.numbers.find({num:{$lte:30}});
21、查询numbers中num大于40小于50的文档
db.numbers.find({num:{$gt:40,$lt:50}});
22、查询numbers中num大于19996的文档
db.numbers.find({num:{$gt:19996}});
23、查询numbers集合中的前10条数据
db.numbers.find().limit(10);
24、查询numbers集合中的第11条到20条数据
db.numbers.find().skip(10).limit(10);
25、查询numbers集合中的第21条到30条数据
// skip((页码-1)*每页显示的条数).limit(每页显示的条数);
db.numbers.find().skip(20).limit(10);
// skip与limit的位置可以互换效果一样
db.numbers.find().limit(10).skip(20);
八、数据库文档之间的关系
1、文档之间的关系:
一对一:在MongoDB,可以通过内嵌文档的形式体现出一对一的关系
db.wifeAndHusband.insert(
[{name:"黄蓉",husband:{name:"郭靖"}},
{name:"谢娜",husband:{name:"张杰"}}
]
);
db.wifeAndHusband.find();
一对多:也可以通过内嵌文档来映射一对多的关系
db.users.insert(
[{username:"swk"},
{username:"zbj"}
]);
db.users.find();
db.order.insert({
list:["猪肉","牛肉"],
user_id:ObjectId("62839c6b07ace0531b630947")
});
db.order.find();
//下面的两句一起执行
//查找用户swk的id
var user_id = db.users.findOne({username:"swk"})._id;
//查找用户swk的订单
db.order.find({user_id:user_id});
多对多:
db.teachers.insert([
{name:"张三"},
{name:"李四"},
{name:"王五"}
]);
db.teachers.find();
db.stus.insert([
{name:"张三丰",tech_ids:[ObjectId("6283a5eb07ace0531b63094b"),
ObjectId("6283a5eb07ace0531b63094c")]},
{name:"李易峰",tech_ids:[ObjectId("6283a5eb07ace0531b63094b"),
ObjectId("6283a5eb07ace0531b63094d")]}
]);
db.stus.find();
九、练习2
1、讲dept和emp集合导入到数据库中
2、查询工资小于2000的员工
db.emp.find({sal:{$lt:2000}});
3、查询工资在1000-2000之间的员工
db.emp.find({sal:{$lt:2000,$gt:1000}});
4、查询工资小于1000或大于2500的员工
// or表示或,数组里面的一个条件满足则输出
db.emp.find({$or:[{sal:{$lt:1000}},{sal:{$gt:2500}}]})
5、查询财务部的所有员工
//先查财务部的Number,再查财务部的员工
var depno = db.dept.findOne({dname:"财务部"}).deptno;
db.emp.find({depno:depno});
6、查询销售部的所有员工
//先查销售部的Number,再查销售部的员工
var depno = db.dept.findOne({dname:"销售部"}).deptno;
db.emp.find({depno:depno});
7、查询所有mgr为7698的所有员工
db.emp.find({mgr:7698});
8、为所有薪资低于1000的员工增加工资400元
//$inc :表示在原值的基础上增加
db.emp.updateMany({sal:{$lte:1000}},{$inc:{sal:400}});
十、MongoDB 的 sort(升序或倒序)和投影(只显示某些字段)
//limit skip sort 可以以任意的顺序进行调用
//按照sal升序排列
db.emp.find({}).sort({sal:1});
//按照sal倒序排列
db.emp.find({}).sort({sal:-1});
//首先按照sal升序,如果sal一样的则按照empno倒序排列
db.emp.find({}).sort({sal:1,empno:-1});
//在查询时,可以在第二个参数的位置来设置查询结果的 投影
//查询出来的结果只显示ename字段,默认情况下id都有
db.emp.find({},{ename:1});
//查询的结果只显示 ename,sal字段,不显示id字段
db.emp.find({},{ename:1,_id:0,sal:1});
十一、Mongoose简介【程序操作数据库】
1、简介
之前我们都是通过shell来完成对数据库的各种操作的,在开发中大部分时候我们都需要通过程序来完成对数据库的操作。而Mongoose 就是一个让我们可以通过Node来操作MongoDB的模块。Mongoose是一个对象文档模型(ODM)库,它对Node原生的MongoDB模块进行了进一步的优化封装,并提供了更多的功能。在大多数情况下,它被用来把结构化的模型应用到一个MongoDB集合,并提供了验证和类型转换等好处。
2、Mongoose的好处
- 可以为文档创建一个模式结构(Schema)【数据进入数据库之前,可以对字段进行约束,对数据类型的约束(如果数据类型不对会自动转换)】
- 可以对模型中的对象/文档进行验证
- 数据可以通过类型转换转换为对象模型
- 可以使用中间件来应用业务逻辑挂钩
- 比Node原生的MongoDB驱动更容易
3、Mongoose新的对象
- Schema(模式对象):定义约束了数据库中的文档结构
- Model:作为集合中的所有文档的表示,相当于MongoDB数据库中的集合collection
- Document:表示集合中的具体文档,相当于集合中的一个具体的文档
4、Mongoose的使用
1)、下载安装Mongoose
-npm install mongoose
2)、在项目中引入mongoose
-const mongoose = require("mongoose")
3)、连接MongoDB数据库
-mongoose.connect("mongodb://数据库IP地址、;端口号/数据库名"),如果端口号是默认的端口号(27017)则可以省略不写
4)、断开连接
-mongoDB数据库,一般情况下,只需要连接一次,连接一次后,除非项目停止服务器关闭,否则连接一般不会断开
-mongoose.disconnect()
5、Schema和Model的使用