Mongodb入门
官方文档:mongoosejs.com/
三个概念:数据库、集合、文档
- 数据库:数据库是一个仓库,再仓库中可以存放集合
- 集合:集合类似于数组,在集合中可以存放文档
- 文档:文档数据库中的最小单位,我们存储和操作的内容都是文档
在mongoDB中,数据库和集合都不需要手动创建
在我们创建文档时,如果文档所在的集合或数据库不存在会自动创建数据库和集合
一、安装mongodb
1.下载地址:www.mongodb.org/dl/win32/ (根据系统版本下载)
2.配置环境变量:把D:\program file\MongoDB\Server\4.4\bin添加到环境变量
有内容说明配置成功
3.在C盘根目录创建一个文件夹data,在data中新建文件夹db(默认数据库目录)
4.启动服务
C:\Users\86183>mongod
5.cmd 连接mongo
通过dbpath指定data路径
--> mongod ---dbpath D:\data\db(示例路径) 默认监听27017
通过--port更换端口
--> mongod ---dbpath D:\data\db(数据库路径) --port 10086(端口号) // 不超过65535
6.数据库
-
数据库的服务器
- 服务器用来保存数据
- mongod用来启动服务器
-
数据库的客户端
- 客户端用来操作服务器,对数据进行增删改查的操作
- mongo用来启动客户端
二、MongoDB的基本操作
1.基本指令
1.显示当前的所有数据库
- show dbs
- show databases
2.进入到指定的数据库中
- use 数据库名
3.db代表的是当前所处的数据库
- db
4.显示数据库中所有的集合
- show collections
2.数据库中的CRUD操作
Ⅰ向数据库中插入文档(自动创建数据库和集合)
当我们向集合中插入文档时,如果没有给文档指定
_id属性,则数据库会自动为文档添加_id(根据时间戳和机器码生成),该属性作为文档的唯一标识
db.<collection>.insert(doc)
-向集合中插入一个或多个文档
-例子:向test数据库中的stus集合中插入一个新的学生对象{name:"孙悟空",age:18,gender:"男"}
db.stus.insert({name:"孙悟空",age:18,gender:"男"})
db.<collection>.find()
查询集合中的所有文档,,,mongodb会自动生成id
安装图形化界面
免费工具官网:www.mongodbmanager.com/download-mo…
解决无法输入中文问题:
调整字体问题:
插入多个文档
db.collection.insertOne() // 插入一个文档对象
db.collection.insertMany() // 插入多个文档对象
// 直接用insert也可以,insertOne和insertMany语义更加清晰
Ⅱ 查询
db.collection.find()
-find() // 查询集合中所有符合条件的文档
-find() // 可以接收一个对象作为条件参数
db.stus.find({_id:"627ca36fd1fc4d6178d4aa19"}) // 返回的是一个数组
db.collection.findOne() // 用来查询集合中符合条件的第一个文档,返回的是一个文档对象
查询有几个文档对象,统计数量
db.collection.find({}).count();
或
db.collection.find({}).length();
Ⅲ 修改
db.collection.update(查询对象,新对象) // update默认情况下只改一个
// update() 默认情况下会使用新对象来替换旧对象
db.stus.update({name:"沙和尚"},{age:28}) // 会将{name:"沙和尚"}一整个文档对象都替换成{age:28} 慎用
如果需要修改指定的属性,而不是替换需要使用“修改操作符”来完成修改 $set可以用来修改文档中的指定属性
$unset 删除文档的指定属性
db.collection.updateMany() // 同时修改多个符合条件的文档
db.collection.updateOne() // 修改一个符合条件的文档
---------------------------
db.collection.updateOne()
// 等价于
db.collection.update()
--------------------
db.collection.updateMany()
// 等价于
db.collection.update(
<query>, // 匹配条件
<update>, // 更新结果
{
multi: true // boolean
}
)
-------------------------------
db.collection.replaceOne() // 替换一个文档
Ⅳ 删除
db.collection.remove() // 删除符合条件的所有文档(默认情况删多个)
db.collection.deleteOne() // 只可以删一个
db.collection.deleteMany() // 只可以删多个
// 传递条件的方式和find一样
---------------------
db.collection.remove()
// 等价于
db.collection.deleteMany()
-----------------------
db.collection.deleteOne()
//等价于
db.collection.remove(
<query>;
<justone> // true
)
--------------------------
// remove 如果只传递一个空对象作为参数,则会删除集合中的所有文档
db.collection.remove({}) // 清空集合(性能略差:一个一个删)
---> 直接删集合,当数据库只有这一个集合时,数据库也会被删除
db.collection.drop();
删除数据库
db.dropDatabase()
db.collection.remove({_id:"qwe"}); // 删除_id为qwe的文档
一般情况下不直接删除数据,设置一个属性值,将需要删除的文档把特定属性值设置为1
假设有这些数据
删除lisi,就把李四的isDel改成1
练习一
1.进入my_test数据库
use my_test;
2.向数据库的user集合中插入一个文档
db.user.insert(
{name:"sunwukong",age:300,sex:"male"}
);
3.查询user集合中的文档
db.user.find();
4.向数据库的user集合中插入一个文档
db.user.insert(
{name:"tangseng",age:30,sex:"male"}
);
5.查询数据库user集合中的文档
db.user.find();
6.统计数据库user集合中的文档数量
db.user.find().count();
7.查询数据库user集合中的name为sunwukong的文档
db.user.find({name:"sunwukong"});
8.向数据库user集合中的name为sunwukong的文档添加一个address属性,属性值为huaguoshan
db.user.update(
{name:"sunwukong"},
{$set:{
address:"huaguoshan"
}}
)
9.使用{name:"zhubajie"} 替换username为tangseng的文档
db.user.update(
{name:"tangseng"},
{$set:{
name:"zhubajie"
}}
);
10.删除name为sunwukong的文档的address属性
db.user.update(
{name:"sunwukong"},
{$unset:{
address:"huaguoshan"
}}
)
11.向name为sunwukong的文档中添加一个hobby:{cities:["beijing","shanghai","shenzhen"],movies:["sanguo","hero"]}
db.user.update(
{name:"sunwukong"},
{$set:{
hobby:{
cities:["beijing","shanghai","shenzhen"],
movies:["sangou","hero"]
}
}}
)
12.向name为zhubajie的文档中,添加一个hobby:{movies:["A Chinese Odyssey","King of comedy"]}
db.user.update(
{name:"zhubajie"},
{$set:{
hobby:{
movies:["A Chinese Odyssey","King of comedy"]
}
}}
);
13.查询喜欢电影hero的文档
// MongoDB支持直接通过内嵌文档的属性进行查询,如果要查询内嵌文档则可以通过.的形式来匹配
// 如果要通过内嵌文档来对文档进行查询,此时属性名必须使用引号
db.user.find({"hobby.movies":"hero"});
14.向zhubajie中添加一个新的电影Interstellar
// 错误示范:直接把hobby.movies里面的值设置为Interstellar,类型是一个字符串
db.user.update(
{name:"zhubajie"},
{$set:{
"hobby.movies":"Interstellar"
}}
);
// 正确写法: $push用于向数组添加一个新的元素 不会考虑元素是否重复
// $addToSet 向数组中添加一个新元素 会考虑元素是否存在,如果已经存在该元素,则不会添加
db.user.update(
{name:"zhubajie"},
{$push:{
"hobby.movies":"Interstellar"
}}
);
15.删除喜欢beijing的用户
db.user.remove(
{"hobby.cities":"beijing"}
);
16.删除user集合
db.user.remove({});
db.user.drop();
17.向numbers中插入20000条数据
for(var i=1;i<=20000;i++){ // 用时 10.2s 效率太低
db.numbers.insert({num:i});
}
// 高性能:0.3s
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});
或:db.numbers.find({num:{$eq:5000}});
19.查询numbers中num大于5000的文档
db.numbers.find({num:{$gt:5000}});
20.查询numbers中num小于30的文档
db.numbers.find({num:{$lt: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({num:{$lt:10}}); // 有序
// limit设置显示数据的上线
db.numbers.find().limit(10);
// 在开发时,绝对不会执行不带条件的查询
24.查看numbers集合中的第11条到第20条数据
// skip()用于跳过指定数量的数据
//skip((页码-1)*每页显示的条数).limit(每页显示的条数)
// skip()和limit()的先后顺序可以变换,mongoDB会自动调整顺序
db.numbers.find().skip(10).limit(10);
25.查看numbers集合中的第21条到第30条数据
db.numbers.find().skip(20).limit(10);
三、文档间的关系
-
一对一 (one to one)【举例:夫妻】
- 在MongoDB,可以通过内嵌文档的形式体现出一对一的关系
-
db.wifeAndhusband.insert( {name:"黄蓉",husband:{name:"郭靖"}}, {name:"潘金莲",husband:{name:"武大郎"}} );
-
一对多 (one to many) / 多对一 (many to one) 【父母-孩子】【用户-订单】
-
也可以通过内嵌文档来映射一对多的关系
// 创建两个用户 db.users.insert([ {username:"swk"}, {username:"zbj"} ]); // 通过绑定id可知这个订单是该用户的 db.orders.insert({ list:["苹果","香蕉","大鸭梨"], user_id:ObjectId("627dbcef816c103eb9437dfb") }); // 一个用户可以有多个订单 db.orders.insert({ list:["嘻哈裤","杰克衫"], user_id:ObjectId("627dbcef816c103eb9437dfb") }); db.orders.insert({ list:["猪肉","鸭肉","漫画"], user_id:ObjectId("627dbcef816c103eb9437dfc") }); // 查找某个用户的订单 var user_id = db.users.findOne({username:"swk"})._id; db.orders.find({user_id:user_id}) -
多对多 (many to many) 【分类--商品】 【老师--学生】
// 老师--学生 db.teachers.insert([ {name: "洪七公"}, {name: "黄药师"}, {name: "龟仙人"}]); // 一个学生对应多个老师 db.stus.update( {name:"zhangsan"}, {$set:{tech_ids:[ ObjectId("627dc1f4816c103eb9437e00"), ObjectId("627dc1f4816c103eb9437e01") ]}} ); // 一个老师对应多个学生 db.teachers.update( {name:"洪七公"}, {$set:{stu_ids:[ ObjectId("627cc3692526994e5ad1b3f5"), ObjectId("627cc3692526994e5ad1b3f6"), ObjectId("627cc3692526994e5ad1b3f7") ]}} );
练习二
26.将dept和emp集合导入到数据库中
27.查询工资小于2000的员工
db.emp.find({sal:{$lt:2000}});
28.查询工资在1000-2000之间的员工
db.emp.find({sal:{$lt:2000,$gt:1000}});
29.查询工资小于1000或大于2500的员工
db.emp.find({
$or:[
{sal:
{$lt:2000}
},
{sal:
{$gt:1000}
}
]
});
30.查询财务部(depno)的所有员工
var deptno = db.dept.findOne({dname:"财务部"}).deptno;
db.emp.find({depno:depno})
31.查询销售部的所有员工
var deptno = db.dept.findOne({dname:"销售部"}).deptno;
db.emp.find({depno:depno})
32.查询所有mgr为7698的所有员工
db.emp.find({mgr:7698}); // 注意数据类型
33.为所有薪资低于1000的员工增加工资400元
// $inc 在原来的基础上进行增加
db.emp.updateMany({sal:{$lte:1000}},{$inc:{sal:400}});
四、sort和投影
Ⅰsort
查询文档时,默认情况是按照_id的值进行排序(升序)
sort()可以用来指定文件的排序规则,sort()需要传递一个对象来指定排序规则,1表示升序,-1表示降序
db.emp.find({}).sort({sal:1,empno:-1}) // 先按照工资升序排序,工资相同的编号按照降序排序
limit skip sort 可以以任意顺序进行进行调用
Ⅱ 投影
// 在查询时,可以在第二个参数的位置来设置查询结果的投影
db.emp.find({},{ename:1}); // 只显示id(默认显示)和姓名
db.emp.find({},{ename:1,_id:0}); // 只显示姓名
五、Mongoose
让我们可以通过Node来操作MongoDB模块
Mongoose是一个对象文档模型库(ODM)
Mongoose的好处
1.可以为文档创建一个模式结构(Schema),约束文档结构,确保数据是对的
2.可以对模型中的对象/文档进行验证
3.数据可以通过类型转换为对象模型
4.可以使用中间件来应用业务逻辑挂钩
5.比Node原生的MongoDB驱动更容易
Mongoose中为我们提供了几个新的对象
-
Schema(模式对象)
- Schema对象定义约束了数据库中的文档结构
-
Model
- Model对象作为集合中的所有文档的表示,相当于MongoDB数据库中的集合collection
-
Document
- Document表示集合中的具体文档,相当于集合中的一个具体文档
\