目录
Mongodb是什么?
数据库是什么 ?
数据库的作用
数据库的主要作用就是 管理数据 ,对数据进行 增(c)、删(d)、改(u)、查(r)
数据库管理数据特点
为什么选择 Mongodb
操作语法与 JavaScript 类似,容易上手,学习成本低
Mongodb核心概念
- 数据库database) 数据库是一个数据仓库,数据库服务下可以创建很多数据库,数据库中可以存 放很多集合
- 集合(collection) 集合类似于 JS 中的数组,在集合中可以存放很多文档
- 文档(document) 文档是数据库中的最小单位,类似于 JS 中的对象
JSON 文件示例:
{
"accounts": [
{
"id": "3-YLju5f3",
"title": "买电脑",
"time": "2023-02-08",
"type": "-1",
"account": "5500",
"remarks": "为了上网课"
},
{
"id": "3-YLju5f4",
"title": "请女朋友吃饭",
"time": "2023-02-08",
"type": "-1",
"account": "214",
"remarks": "情人节聚餐"
},
{
"id": "mRQiD4s3K",
"title": "发工资",
"time": "2023-02-19",
"type": "1",
"account": "4396",
"remarks": "终于发工资啦!~~"
}
],
"users":[
{
"id": 1,
"name": "zhangsan",
"age": 18
},
{
"id": 2,
"name": "lisi",
"age": 20
},
{
"id": 3,
"name": "wangwu",
"age": 22
}
]
}
一个json文件就相当于一个数据库,accounts和users就相当于是collection,accounts和users里面的对象就相当于是doucument,对象中的属性(如name、id等称之为字段)
- 一个 JSON 文件 好比是一个 数据库 ,一个 Mongodb 服务下可以有 N 个数据库
- JSON 文件中的 一级属性的数组值 好比是 集合
- 数组中的对象好比是 文档
- 对象中的属性有时也称之为 字段
一般情况下
Mongodb的下载与安装
建议选择 zip 类型, 通用性更强
配置步骤如下:
- 将压缩包移动到 你喜欢的盘下,然后解压
- 创建 E:\data\db 目录,mongodb 会将数据默认保存在这个文件夹
- 以 mongodb 中 bin 目录作为工作目录,启动命令行
- 运行命令 mongod
看到最后的 waiting for connections 则表明服务 已经启动成功
数据库命令
1. 显示所有的数据库
show dbs
2. 切换到指定的数据库,如果数据库不存在会自动创建数据库
use 数据库名
3. 显示当前所在的数据库
db
4. 删除当前数据库
use 库名
db.dropDatabase()
集合命令
1. 创建集合
db.createCollection('集合名称')
2. 显示当前数据库中的所有集合
show collections
3. 删除某个集合
db.集合名.drop()
4. 重命名集合
db.集合名.renameCollection('newName')
文档命令
1. 插入文档
db.集合名.insert(文档对象);
//例如
db.user.insert({name:'森树',age:30})
2. 查询文档
db.集合名.find(查询条件)
//例如
db.user.find()
db.user.find({age:30})
3. 更新文档
db.集合名.update(查询条件,新的文档)
db.集合名.update({name:'张三'},{$set:{age:19}})
4. 删除文档
db.集合名.remove(查询条件)
应用场景
- 用户注册
- 发布视频
- 发布商品
- 发朋友圈
- 发评论
- 发微博
- 发弹幕
- .......
- 删除评论
- 删除商品
- 删除文章
- 删除视频
- 删除微博
- ......
- 更新个人信息
- 修改商品价格
- 修改文章内容
- ......
- 商品列表
- 视频列表
- 朋友圈列表
- 微博列表
- 搜索功能
- ......
Mongoose
使用流程:
连接数据库:
//1、安装mongoose
//2、导入mongoose
const mongoose = require('mongoose');
//3、连接mongodb服务 数据库名称
mongoose.connect('mongodb://127.0.0.1:27017/books');
//4、设置回调
//设置连接成功的回调
mongoose.connection.on('open',()=>{
console.log('连接成功');
});
//设置连接错误的回调
mongoose.connection.on('error',()=>{
console.log('连接失败');
});
//设置连接关闭的回调
mongoose.connection.on('close',()=>{
console.log('连接关闭');
});
//关闭mongodb的连接
setTimeout(()=>{
mongoose.disconnect();
},2000)
注意:官方建议把on换成once
Mongoose插入文档
//1、安装mongoose
//2、导入mongoose
const mongoose = require('mongoose');
//3、连接mongodb服务 数据库名称
mongoose.connect('mongodb://127.0.0.1:27017/books');
//4、设置回调
//设置连接成功的回调
mongoose.connection.on('open',()=>{
// console.log('连接成功');
//5、创建文档中的结构对象
//设置集合中的文档属性以及属性值的类型
let BookSchma=new mongoose.Schema({
name:String,
author:String,
price:Number
});
//6、创建模型对象,对文档操作的封装对象
let BookModel=mongoose.model('books',BookSchma);
//新增
BookModel.create({
name:'西游记',
author:'吴承恩',
price:19.9
},(err,data)=>{
//判断是否有错误
if(err){
console.log(err);
return;
}
//如果没有出错,则输出插入后文档对象
console.log(data);
//8、关闭数据库连接(项目运行过程中,不会添加改代码)
mongoose.disconnect();
});
});
//设置连接错误的回调
mongoose.connection.on('error',()=>{
console.log('连接失败');
});
//设置连接关闭的回调
mongoose.connection.on('close',()=>{
console.log('连接关闭');
});
注意:7版本的会报错:
throw new MongooseError('Model.create() no longer accepts a callback');
原因:从6.0.0版开始,Mongoose中的方法不再接受回调作为最后一个参数,而是返回一个promise。2您应该更新代码,使用promise来处理create()方法的结果
或者手动下载6版本即可。
npm install mongoose@6.0.0
Mongoose字段类型
类型 | 描述 |
String | 字符串 |
Number | 数字 |
Boolean | 布尔值 |
Array | 数组,也可以使用[ ]来标识 |
Date | 日期 |
Buffer | Buffer对象 |
Mixed |
任意类型,需要使用
mongoose.Schema.Types.Mixed
指定
|
ObjectId |
对象
ID
,需要使用
mongoose.Schema.Types.ObjectId
指定,文档ID,相当于外键,用于联合文档查询用
|
Decimal128
|
高精度数字,需要使用
mongoose.Schema.Types.Decimal128
指定
|
//1、安装mongoose
//2、导入mongoose
const mongoose = require('mongoose');
//3、连接mongodb服务 数据库名称
mongoose.connect('mongodb://127.0.0.1:27017/books');
//4、设置回调
//设置连接成功的回调
mongoose.connection.on('open',()=>{
// console.log('连接成功');
//5、创建文档中的结构对象
//设置集合中的文档属性以及属性值的类型
let BookSchma=new mongoose.Schema({
name:String,
author:String,
price:Number,
is_hot:Boolean,
tags:Array,
publish_time:Date,
test:mongoose.Schema.Types.Mixed,
test2:mongoose.Schema.Types.ObjectId, //文档ID,相当于外键,用于联合文档查询用
});
//6、创建模型对象,对文档操作的封装对象
let BookModel=mongoose.model('books',BookSchma);
//新增
BookModel.create({
name:'西游记',
author:'吴承恩',
price:19.9,
is_hot:true,
tags:['鬼怪','励致','社会'],
publish_time:new Date(),
test:123 //test可以随意给值
},(err,data)=>{
//判断是否有错误
if(err){
console.log(err);
return;
}
//如果没有出错,则输出插入后文档对象
console.log(data);
//8、关闭数据库连接(项目运行过程中,不会添加改代码)
mongoose.disconnect();
});
});
//设置连接错误的回调
mongoose.connection.on('error',()=>{
console.log('连接失败');
});
//设置连接关闭的回调
mongoose.connection.on('close',()=>{
console.log('连接关闭');
});
字段值验证
文档属性的值校验,Mongoose 有一些内建验证器,可以对字段值进行验证
必填项
title: {
type: String,
required: true // 设置必填项
},
默认值
author: {
type: String,
default: '匿名' //默认值
},
枚举值
gender: {
type: String,
enum: ['男','女'] //设置的值必须是数组中的
},
唯一值
username: {
type: String,
unique: true
},
//1、安装mongoose
//2、导入mongoose
const mongoose = require('mongoose');
//3、连接mongodb服务 数据库名称
mongoose.connect('mongodb://127.0.0.1:27017/books');
//4、设置回调
//设置连接成功的回调
mongoose.connection.on('open',()=>{
// console.log('连接成功');
//5、创建文档中的结构对象
//设置集合中的文档属性以及属性值的类型
let BookSchma=new mongoose.Schema({
name:{
type:String,
require:true, //表明该属性必须不为空
unique:true //设置为独一无二的
},
author:{
type:String,
default:'匿名'
},
//类型
types:{
type:String,
//枚举
enum:['言情','志怪','城市','恐怖']
},
price:Number,
is_hot:Boolean,
tags:Array,
publish_time:Date,
test:mongoose.Schema.Types.Mixed,
test2:mongoose.Schema.Types.ObjectId, //文档ID,相当于外键,用于联合文档查询用
});
//6、创建模型对象,对文档操作的封装对象
let BookModel=mongoose.model('books',BookSchma);
//新增
BookModel.create({
name:'西游记',
// author:'吴承恩',
types:'志怪',
price:19.9,
is_hot:true,
tags:['鬼怪','励致','社会'],
publish_time:new Date(),
test:123 //test可以随意给值
},(err,data)=>{
//判断是否有错误
if(err){
console.log(err);
return;
}
//如果没有出错,则输出插入后文档对象
console.log(data);
//8、关闭数据库连接(项目运行过程中,不会添加改代码)
mongoose.disconnect();
});
});
//设置连接错误的回调
mongoose.connection.on('error',()=>{
console.log('连接失败');
});
//设置连接关闭的回调
mongoose.connection.on('close',()=>{
console.log('连接关闭');
});
Mongoose删除文档
增加
插入一条
SongModel.create({
title:'给我一首歌的时间',
author: 'Jay'
}, function(err, data){
//错误
console.log(err);
//插入后的数据对象
console.log(data);
});
//1.引入mongoose
const mongoose = require('mongoose');
//2.链接mongodb数据库 connect 连接
mongoose.connect('mongodb://127.0.0.1:27017/project');
//3.设置连接的回调
mongoose.connection.on('open',()=>{
//4.声明文档结构
const PhoneSchema = new mongoose.Schema({
brand:String,
color:String,
price:Number,
tags:Array
})
//6.创建模型对象
const PhoneModel = mongoose.model('phone',PhoneSchema);
PhoneModel.insertMany([
{
brand:'华为',
color:'灰色',
price:2399,
tags:['电量大','屏幕大','信号好']
},
{
brand:'小米',
color:'白色',
price:2099,
tags:['电量大','屏幕大','信号好']
}
],(err,data)=>{
if(err) throw err;
console.log('写入成功');
mongoose.connection.close();
})
})
删除
SongModel.deleteOne({_id:'5dd65f32be6401035cb5b1ed'}, function(err){
if(err) throw err;
console.log('删除成功');
mongoose.connection.close();
});
SongModel.deleteMany({author:'Jay'}, function(err){
if(err) throw err;
console.log('删除成功');
mongoose.connection.close();
});
案例
//1、安装mongoose
//2、导入mongoose
const mongoose = require('mongoose');
//3、连接mongodb服务 数据库名称
mongoose.connect('mongodb://127.0.0.1:27017/books');
//4、设置回调
//设置连接成功的回调
mongoose.connection.on('open',()=>{
// console.log('连接成功');
//5、创建文档中的结构对象
//设置集合中的文档属性以及属性值的类型
let BookSchma=new mongoose.Schema({
name:{
type:String,
require:true, //表明该属性必须不为空
unique:true //设置为独一无二的
},
author:{
type:String,
default:'匿名'
},
//类型
types:{
type:String,
//枚举
enum:['言情','志怪','城市','恐怖']
},
price:Number,
is_hot:Boolean,
tags:Array,
publish_time:Date,
test:mongoose.Schema.Types.Mixed,
test2:mongoose.Schema.Types.ObjectId, //文档ID,相当于外键,用于联合文档查询用
});
//6、创建模型对象,对文档操作的封装对象
let BookModel=mongoose.model('novel',BookSchma);
//删除一条
BookModel.deleteOne({_id:'643b6af31798c9cfab91aae6'},(err,data)=>{
//判断
if(err){
console.log(err);
return;
}
//输出data
console.log(data);
});
//批量删除
BookModel.deleteMany({is_hot:false},(err,data)=>{
//判断
if(err){
console.log(err);
return;
}
//输出data
console.log(data);
});
});
//设置连接错误的回调
mongoose.connection.on('error',()=>{
console.log('连接失败');
});
//设置连接关闭的回调
mongoose.connection.on('close',()=>{
console.log('连接关闭');
});
Mongoose更新文档
更新一条数据
SongModel.updateOne({author: 'JJ Lin'}, {author: '林俊杰'}, function (err) {
if(err) throw err;
mongoose.connection.close();
});
批量更新数据
SongModel.updateMany({author: 'Leehom Wang'}, {author: '王力宏'}, function (err) {
if(err) throw err;
mongoose.connection.close();
});
案例:
//7.更新文档 更新一条 (条件,新的内容,回调函数)
BookModel.updateOne({name:'红楼梦'},{price:9.9},(err,data)=>{
if(err){
console.log('更新失败');
return;
}
//输出data
console.log(data);
});
//批量更新
BookModel.updateMany({author:'余华'},{is_hot:false},(err,data)=>{
if(err){
console.log('更新失败');
return;
}
//输出data
console.log(data);
});
Mongoose读取(查询)文档
查询一条数据
SongModel.findOne({author: '王力宏'}, function(err, data){
if(err) throw err;
console.log(data);
mongoose.connection.close();
});
//根据 id 查询数据
SongModel.findById('5dd662b5381fc316b44ce167',function(err, data){
if(err) throw err;
console.log(data);
mongoose.connection.close();
});
批量查询数据
//不加条件查询
SongModel.find(function(err, data){
if(err) throw err;
console.log(data);
mongoose.connection.close();
});
//加条件查询
SongModel.find({author: '王力宏'}, function(err, data){
if(err) throw err;
console.log(data);
mongoose.connection.close();
});
Mongoose条件控制
运算符
- > 使用 $gt
- < 使用 $lt
- >= 使用 $gte
- <= 使用 $lte
- !== 使用 $ne
db.students.find({id:{$gt:3}}); id号比3大的所有的记录
//价格小于20的书
BookModel.find({price:{$lt:20}},(err,data)=>{
if(err){
console.log('读取失败');
return;
}
console.log(data);
});
逻辑运算
db.students.find({$or:[{age:18},{age:24}]});
//曹雪芹或余华的书
BookModel.find({$or:[{author:'曹雪芹'},{author:'余华'}]},(err,data)=>{
if(err){
console.log('读取失败');
return;
}
console.log(data);
});
db.students.find({$and: [{age: {$lt:20}}, {age: {$gt: 15}}]});
// 价格大于30且小于70
BookModel.find({$and:[{price:{$gt:30}},{price:{$lt:70}}]},(err,data)=>{
if(err){
console.log('读取失败');
return;
}
console.log(data);
});
正则匹配
db.students.find({name:/imissyou/});
//正则表达式 搜索书名中带“三”的书籍
BookModel.find({name:/三/},(err,data)=>{
if(err){
console.log('读取失败');
return;
}
console.log(data);
});
//正则另一种方式
BookModel.find({name:new RegExp('三')},(err,data)=>{
if(err){
console.log('读取失败');
return;
}
console.log(data);
});
});
Mongoose个性化读取
字段筛选
//0:不要的字段
//1:要的字段
SongModel.find().select({_id:0,title:1}).exec(function(err,data){
if(err) throw err;
console.log(data);
mongoose.connection.close();
});
//7.设置字段
BookModel.find().select({name:1,author:1,_id:0}).exec((err,data)=>{
if(err){
console.log('查询失败');
return;
}
console.log(data);
});
数据排序
//sort 排序
//1:升序
//-1:倒序
SongModel.find().sort({hot:1}).exec(function(err,data){
if(err) throw err;
console.log(data);
mongoose.connection.close();
});
//数据排序
BookModel.find().select({name:1,price:1,_id:0}).sort({price:1}).exec((err,data)=>{
if(err){
console.log('查询失败');
return;
}
console.log(data);
});
数据截取
//skip 跳过 limit 限定
SongModel.find().skip(10).limit(10).exec(function(err,data){
if(err) throw err;
console.log(data);
mongoose.connection.close();
});
//数据的截取
//取前三
BookModel.find().select({name:1,price:1,_id:0}).sort({price:1}).limit(3).exec((err,data)=>{
if(err){
console.log('查询失败');
return;
}
console.log(data);
});
//取4-6,跳过123
BookModel.find()
.select({name:1,price:1,_id:0})
.sort({price:1})
.skip(3)
.limit(3)
.exec((err,data)=>{
if(err){
console.log('查询失败');
return;
}
console.log(data);
});
Mongoose代码模块化
详情见‘08_mongoose模块化’文件
案例:
文件分配:
index.js
//导入db文件
const db=require('./db/db');
//导入mongoose
const mongoose=require('mongoose');
//导入BookModel
const BookModel=require('./models/BookModel');
//调用回调函数
db(()=>{
// console.log('连接成功');
//新增
BookModel.create({
name:'中国文化',
author:'吴承恩',
price:19.9,
is_hot:true,
tags:['鬼怪','励致','社会'],
publish_time:new Date(),
test:123 //test可以随意给值
},(err,data)=>{
//判断是否有错误
if(err){
console.log(err);
return;
}
//如果没有出错,则输出插入后文档对象
console.log(data);
//8、关闭数据库连接(项目运行过程中,不会添加改代码)
mongoose.disconnect();
});
},()=>{
console.log('连接失败')
})
BookModel.js(在models文件夹下存放)
//导入模块
const mongoose=require('mongoose');
//创建文档中的结构对象
//设置集合中的文档属性以及属性值的类型
let BookSchma=new mongoose.Schema({
name:String,
author:String,
price:Number,
is_hot:Boolean,
tags:Array,
publish_time:Date,
test:mongoose.Schema.Types.Mixed,
test2:mongoose.Schema.Types.ObjectId, //文档ID,相当于外键,用于联合文档查询用
});
//创建模型对象,对文档操作的封装对象
let BookModel=mongoose.model('books',BookSchma);
//暴露模型对象
module.exports = BookModel;
db.js(连接数据库操作,在db文件下存放)
//success:数据成功的回调,error数据失败的回调
module.exports=function(success,error){
//判断error为其设置默认值
if(typeof error !== 'function'){
error=()=>{
console.log('连接失败')
}
}
//1、安装mongoose
//2、导入mongoose
const mongoose = require('mongoose');
//导入配置文件 ,解构赋值
const {DBHOST,DBPORT,DBNAME}=require('../config/config');
//3、连接mongodb服务 数据库名称
mongoose.connect(`mongodb://${DBHOST}:${DBPORT}/${DBNAME}`);
//4、设置回调
//设置连接成功的回调
mongoose.connection.on('open',()=>{
success();
});
//设置连接错误的回调
mongoose.connection.on('error',()=>{
error();
});
//设置连接关闭的回调
mongoose.connection.on('close',()=>{
console.log('连接关闭');
});
}
config.js(配置文件,在config文件下存放)方便以后修改服务器名,端口号,数据库名
//配置文件
module.exports={
DBHOST:'127.0.0.1',
DBPORT:'27017',
DBNAME:'books'
}
写代码基本流程:db.js --> index.js --> BookModel.js --> config.js
Mongodb图形化工具 Robo 3T
1、R obo 3T 免费 https://github.com/Studio3T/robomongo/releases
要先开启mongod服务器,才能连接。
2、Navicat 收费 https://www.navicat.com.cn/
要先开启mongod服务器,然后双击mongodb数据库。
新建数据快捷键:tab键。
=========================================================================
记账本案例优化
结合数据库
1、项目目录结构:
2、编辑www.js文件
创建模型文件
AccountModel.js
//导入模块
const mongoose=require('mongoose');
//创建文档中的结构对象
//设置集合中的文档属性以及属性值的类型
let AccountSchema=new mongoose.Schema({
//标题
title:{
type:String,
required:true
},
//时间
time:Date,
//类型
type:{
type:Number,
default:-1
},
//金额
account:{
type:Number,
required:true
},
//备注
remarks:{
type:String
}
});
//创建模型对象,对文档操作的封装对象
let AccountModel=mongoose.model('accounts',AccountSchema);
//暴露模型对象
module.exports = AccountModel;
插入数据库
注意:时间是一个字符串要转换成对象Object,再转换成时间Date(借助moment工具包)
npm i moment
index.js里新增如下代码
成功!
读取数据库
index.js新增如下代码
删除数据
list.ejs新增代码:
index.js新增代码:
list.ejs新增代码:
跳转到这里来