nodeJs+express+Mongodb+mongoose+Navicat
自我记录
一、简介
1.1 Mongodb 是什么
MongoDB 是一个基于分布式文件存储的数据库,官方地址 https://www.mongodb.com/
1.2 数据库是什么
数据库(DataBase)是按照数据结构来组织、存储和管理数据的 应用程序
1.3 数据库的作用
数据库的主要作用就是 管理数据
,对数据进行 增(c)、删(d)、改(u)、查(r)
1.4 数据库管理数据的特点
相比于纯文件管理数据,数据库管理数据有如下特点:
- 速度更快
- 扩展性更强
- 安全性更强
1.5 为什么选择 Mongodb
操作语法与 JavaScript 类似,容易上手,学习成本低
二、核心概念
Mongodb 中有三个重要概念需要掌握
数据库(database) 数据库是一个数据仓库,数据库服务下可以创建很多数据库,数据库中可以存
放很多集合
集合(collection) 集合类似于 JS 中的数组,在集合中可以存放很多文档
文档(document) 文档是数据库中的最小单位,类似于 JS 中的对象
三、下载安装与启动
下载地址:https://www.mongodb.com/try/download/community
我选择的是 5.0.21
版本
建议选择zip
类型, 通用性更强
配置步骤如下
:
1> 将压缩包移动到 C:\Program Files
下,然后解压
2> 创建 C:\data\db
目录,mongodb
会将数据默认保存在这个文件夹
3> 以 mongodb
中 bin
目录作为工作目录,启动命令行
4> 运行命令 mongod
看到最后的waiting for connections
则表明服务 已经启动成功
然后可以使用 mongo
命令连接本机的 mongodb 服务
注意:
为了方便后续方便使用 mongod 命令,可以将bin
目录配置到环境变量Path
中
千万不要选中服务端窗口的内容
,选中会停止服务,可以敲回车
取消选中
四、命令行交互
命令行交互一般是学习数据库的第一步,不过这些命令在后续用的比较少,所以大家了解即可
4.1 数据库命令
- 显示所有的数据库
show dbs
- 切换到指定的数据库,如果数据库不存在会自动创建数据库
use 数据库名
- 显示当前所在的数据库
db
- 删除当前数据库
use 库名 db.dropDatabase()
4.2 集合命令
- 创建集合
db.createCollection('集合名称')
- 显示当前数据库中的所有集合
show collections
- 删除某个集合
db.集合名.drop()
- 重命名集合
db.集合名.renameCollection('newName')
4.3 文档命令
-
插入文档
db.集合名.insert(文档对象);
-
查询文档
db.集合名.find(查询条件);
_id 是 mongodb 自动生成的唯一编号,用来唯一标识文档
-
更新文档
db.集合名.update(查询条件,新的文档) db.集合名.update({name:'张三'},{$set:{age:19}})
-
删除文档
db.集合名.remove(查询条件)
4.4 应用场景
4.4.1 新增
用户注册
发布视频
发布商品
发朋友圈
发评论
发微博
发弹幕
…
4.4.2 删除
删除评论
删除商品
删除文章
删除视频
删除微博
…
4.4.3 更新
更新个人信息
修改商品价格
修改文章内容
…
4.4.4 查询
商品列表
视频列表
朋友圈列表
微博列表
搜索功能
…
五、Mongoose
5.1 介绍
Mongoose 是一个对象文档模型库,官网 http://www.mongoosejs.net/
5.2 作用
方便使用代码操作 mongodb 数据库
5.3 使用流程
5.3.1 运行MongoDB
按照三去下载并运行 mongod
和 mongo
C:\Program Files\MongoDB\Server\5.0\bin>mongod
C:\Program Files\MongoDB\Server\5.0\bin>mongo
5.3.2 初始化项目 package.json
npm init
nodemon
没有的话要全局安装一下
官网地址: https://nodemon.io/
github地址:https://github.com/remy/nodemon/
npm i -g nodemon
并配置命令 dev & serve
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
+ "dev": "nodemon ./app.js",
+ "serve": "node ./app.js"
},
"author": "",
"license": "ISC"
}
5.3.3 运行并简单使用
在 app.js
// 1.安装 mongoose
// 2.导入 mongoose
const mongoose = require("mongoose");
// 3.链接 mongodb 服务 test 数据库的名称
mongoose.connect("mongodb://127.0.0.1:27017/test");
// 5. 创建文档的结构对象
// 设置集合中 文档的属性 以及类型值
let BookSchema = new mongoose.Schema({
name: {
type: String,
required: true, // 必填
unique: true // 独一无二 新集合才可以
},
author: {
type: String,
default: '匿名' // 默认值
},
gender: {
type: String,
enum: ['男', '女'] // 枚举 必须是里面的内容
},
price: Number,
is_hot: Boolean,
// tag: Array,
// pub_time: Date,
});
// 6.创建模型对象 : mongoose 会使用集合的复数去创建集合
let BookModel = mongoose.model("books", BookSchema);
const createBook = async () => {
try {
// 7.新增
const data = await BookModel.create({
name: '红楼梦1',
author: '张三',
gender: '男',
price: 99,
is_hot: true,
// tag: ['法律', '大佬'],
// pub_time: new Date()
})
console.log(data);
// 8.关闭数据库连接 项目运行中不会添加该代码
mongoose.disconnect()
} catch (err) {
// 处理错误
console.error('Error creating user:', err);
return
}
}
// 单条删除
const delBook = async () => {
// 删除
try {
const data = await BookModel.deleteOne({ _id: '650cff4da98f11a93e431184' })
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('单条删除失败');
return;
}
}
};
// 批量删除
const dellManyBook = async () => {
// 批量删除
try {
const data = await BookModel.deleteMany({ is_hot: true })
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('批量删除失败');
return;
}
}
};
// 单条更新
const updateBook = async () => {
// 删除
try {
const data = await BookModel.updateOne({ name: '红楼梦' },{price:990})
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('更新失败');
return;
}
}
}
// 批量更新
const updateManyBook = async () => {
// 批量更新
try {
const data = await BookModel.updateMany({ is_hot: false },{price:9.9})
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('批量更新失败');
return;
}
}
}
// 单条读取
const findBook = async () => {
try {
const data = await BookModel.findOne({ name: '法外狂徒' })
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('单条读取失败');
return;
}
}
};
// ID读取
const findIDBook = async () => {
try {
const data = await BookModel.findById('650d01e4761830fc4b8d21e7')
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('单条ID读取失败');
return;
}
}
};
// 批量读取 or 读取所有
const findManyBook = async () => {
try {
// const data = await BookModel.find({price: 9.9})
const data = await BookModel.find()
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('批量读取 or 读取所有失败');
return;
}
}
};
// 条件读取
/**
* @findRuleBook 条件读取
* @$gt : >
* @$lt : <
* @$gte : >=
* @$lte : <=
* @$ne : !==
* @$or : ||
* @$and : &&
*/
const findRuleBook = async () => {
try {
// // < 9.9的
// const data = await BookModel.find({price: {$lt:9.9}})
// // 名字是 法外狂徒 或者 价格是 99的
// const data = await BookModel.find({$or:[{name:'法外狂徒'},{price:99}]})
// // > 9.9 && < 990
// const data = await BookModel.find({ $and: [{ price: {$gt:9.9 } },{price:{$lt:990}}]})
// // 正则表达式检索 带有 '1' 的名字 或者 new RegExp('1')
const data = await BookModel.find({name:/1/})
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('条件读取失败');
return;
}
}
};
// 个性化读取-设置字段形式
const findSelectBook = async () => {
try {
// 只要name 和 author字段 (id:0 不写的话默认返回id)
const data = await BookModel.find().select({ name:1,author:1,_id:0})
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('个性化读取失败');
return;
}
}
};
// 个性化读取-数据排序
const findSortBook = async () => {
try {
// sort({price:-1}) -1 为倒叙 1为正序 也可以配合select使用
const data = await BookModel.find().select({ name:1,price:1,_id:0}).sort({price:-1})
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('个性化读取失败');
return;
}
}
};
// 个性化读取-数据截取
/**
* @findSkipLimitBook 数据截取
* @skip 跳过
* @limit 限定
*/
const findSkipLimitBook = async () => {
try {
// skip(1) 跳过第一个 limit(2)取两个
const data = await BookModel.find().skip(1).limit(2).select({ name:1,price:1,_id:0}).sort({price:-1})
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('个性化读取失败');
return;
}
}
};
// 4.设置回调
// 连接成功的回调
const db = mongoose.connection;
db.once("open", () => {
console.log("成功");
// createBook()
// delBook()
// dellManyBook()
// updateBook()
// updateManyBook()
// findBook()
// findIDBook()
// findManyBook()
// findRuleBook()
// findSelectBook()
// findSortBook()
findSkipLimitBook()
});
// 连接出错的回调
db.on("error", () => {
console.log("失败");
});
// 连接关闭的回调
db.on("close", () => {
console.log("关闭");
});
5.4 优化 - 模块化使用
5.4.1 同级新建 db/db.js
抽离公共的连接
/**
*
* @param {*} success 数据库链接成功的回调
* @param {*} 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 服务 DBNAME 数据库的名称
mongoose.connect(`mongodb://${DBHOST}:${DBPORT}/${DBNAME}`);
// 4.设置回调
// 连接成功的回调
const db = mongoose.connection;
// 连接成功的回调 once 只执行一次 事件回调函数只会执行一次
db.once("open", () => {
success();
});
// 连接出错的回调
db.on("error", () => {
error();
});
// 连接关闭的回调
db.on("close", () => {
console.log("连接关闭");
});
}
5.4.2 同级新建 models/BookModel.js
抽离公共的文档的结构对象和集合
// 导入 mongoose
const mongoose = require('mongoose')
// 5. 创建文档的结构对象
// 设置集合中 文档的属性 以及类型值
let BookSchema = new mongoose.Schema({
name: {
type: String,
required: true, // 必填
unique: true // 独一无二 新集合才可以
},
author: {
type: String,
default: '匿名' // 默认值
},
gender: {
type: String,
enum: ['男', '女'] // 枚举 必须是里面的内容
},
price: Number,
is_hot: Boolean,
// tag: Array,
// pub_time: Date,
});
// 6.创建模型对象 : mongoose 会使用集合的复数去创建集合
let BookModel = mongoose.model("books", BookSchema);
// 暴露模型对象
module.exports = BookModel
5.4.3 同级新建 config/config.js
提取公共的配置文件
// 配置文件
module.exports = {
DBHOST: '127.0.0.1',
DBPORT: '27017',
DBNAME: 'test'
}
5.4.4 最后同级的 app.js
使用
// 导入db文件
const db = require('./db/db')
// 导入 mongoose
const mongoose = require('mongoose')
// 导入 BookModel
const BookModel = require('./models/BookModel')
// 调用函数
db(() => {
console.log('连接成功');
// createBook()
// delBook()
// dellManyBook()
// updateBook()
// updateManyBook()
// findBook()
// findIDBook()
// findManyBook()
// findRuleBook()
// findSelectBook()
// findSortBook()
findSkipLimitBook()
})
const createBook = async () => {
try {
// 7.新增
const data = await BookModel.create({
name: '红楼梦1',
author: '张三',
gender: '男',
price: 99,
is_hot: true,
// tag: ['法律', '大佬'],
// pub_time: new Date()
})
console.log(data);
// 8.关闭数据库连接 项目运行中不会添加该代码
mongoose.disconnect()
} catch (err) {
// 处理错误
console.error('Error creating user:', err);
return
}
}
// 单条删除
const delBook = async () => {
// 删除
try {
const data = await BookModel.deleteOne({ _id: '650cff4da98f11a93e431184' })
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('单条删除失败');
return;
}
}
};
// 批量删除
const dellManyBook = async () => {
// 批量删除
try {
const data = await BookModel.deleteMany({ is_hot: true })
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('批量删除失败');
return;
}
}
};
// 单条更新
const updateBook = async () => {
// 删除
try {
const data = await BookModel.updateOne({ name: '红楼梦' },{price:990})
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('更新失败');
return;
}
}
}
// 批量更新
const updateManyBook = async () => {
// 批量更新
try {
const data = await BookModel.updateMany({ is_hot: false },{price:9.9})
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('批量更新失败');
return;
}
}
}
// 单条读取
const findBook = async () => {
try {
const data = await BookModel.findOne({ name: '法外狂徒' })
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('单条读取失败');
return;
}
}
};
// ID读取
const findIDBook = async () => {
try {
const data = await BookModel.findById('650d01e4761830fc4b8d21e7')
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('单条ID读取失败');
return;
}
}
};
// 批量读取 or 读取所有
const findManyBook = async () => {
try {
// const data = await BookModel.find({price: 9.9})
const data = await BookModel.find()
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('批量读取 or 读取所有失败');
return;
}
}
};
// 条件读取
/**
* @findRuleBook 条件读取
* @$gt : >
* @$lt : <
* @$gte : >=
* @$lte : <=
* @$ne : !==
* @$or : ||
* @$and : &&
*/
const findRuleBook = async () => {
try {
// // < 9.9的
// const data = await BookModel.find({price: {$lt:9.9}})
// // 名字是 法外狂徒 或者 价格是 99的
// const data = await BookModel.find({$or:[{name:'法外狂徒'},{price:99}]})
// // > 9.9 && < 990
// const data = await BookModel.find({ $and: [{ price: {$gt:9.9 } },{price:{$lt:990}}]})
// // 正则表达式检索 带有 '1' 的名字 或者 new RegExp('1')
const data = await BookModel.find({name:/1/})
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('条件读取失败');
return;
}
}
};
// 个性化读取-设置字段形式
const findSelectBook = async () => {
try {
// 只要name 和 author字段 (id:0 不写的话默认返回id)
const data = await BookModel.find().select({ name:1,author:1,_id:0})
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('个性化读取失败');
return;
}
}
};
// 个性化读取-数据排序
const findSortBook = async () => {
try {
// sort({price:-1}) -1 为倒叙 1为正序 也可以配合select使用
const data = await BookModel.find().select({ name:1,price:1,_id:0}).sort({price:-1})
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('个性化读取失败');
return;
}
}
};
// 个性化读取-数据截取
/**
* @findSkipLimitBook 数据截取
* @skip 跳过
* @limit 限定
*/
const findSkipLimitBook = async () => {
try {
// skip(1) 跳过第一个 limit(2)取两个
const data = await BookModel.find().skip(1).limit(2).select({ name:1,price:1,_id:0}).sort({price:-1})
console.log(data);
mongoose.disconnect()
} catch (err) {
if (err) {
console.log('个性化读取失败');
return;
}
}
};