mogoose 创建数据库并增删改查
下载
npm i mongoose -s
连接数据库
const mongoose = require("mongoose");
mongoose.connect(dbURL);
const db = mongoose.connection;
db.on("error", () => {
console.log("链接失败");
});
db.on("open", () => {
console.log("链接成功");
});
创建表结构Schema
Schema相当于MySql的表结构
通过定义Schema来约束数据的类型,支持以下类型数据
| 类型 | 作用 |
|---|---|
| String | 定义字符串 |
| Number | 定义数字 |
| Date | 定义日期 |
| Buffer | 定义二进制 |
| Boolean | 定义布尔值 |
| Mixed | 定义混合类型 |
| ObjectId | 定义对象ID |
| Array | 定义数组 |
| Decimal128 | |
| Map |
约束能用对象的方法描述数据类型 是否必须 是否重复 默认值 等,如下定义了一个用户表结构
注意:如果定义表结构时没有定义
_id,mongoose会自己添加一个该字段,该字段不会重复,类型为ObjectId,通过findById()查询
const userSachem = new mongoose.Schema(
{
name: {
type: String,
required: true, //! 必须
},
email: {
type: String,
required: true,
unique: true, //! 不重复
},
passWord: {
type: String,
required: true,
},
avatar: {
type: String,
default: null, //! 默认值
},
bio: String, //! 默认没有可以不写
},
{
timestamps: true, //! 添加`createdAt updatedAt`创建时间和更新时间两个字段
}
);
如果在定义了结构后需要添加新字段,在实例上使用add()方法
创建表model
通过mongoose.model(name,sechem)来创建表结构构造器,通过传入数据来实例化构造器获得具体的表
注意:在这一步的时候数据库已经有了表,表名全是小写且表明为name加上s,如这里会创建表
users
const User = mongoose.model("User", userSechem);
通过上面的操作就获得了表的构造函数,接下来就可以向里面进行增删改查了
增
有三种方法在表内增加数据:
通过实例化数据:
- 创建表数据
实例化model
通过传入具体的数据来实例化表,能获得一条具体的表数据,类型为Mongoose Documents,向数据库中查找到的也是这种类型数据
const user = new User(userData);
- 保存
save
获得具体的表后只需要调用Model.prototype.save就会把数据存入数据库中 注意:该方法为异步方法
await user.save();
通过Model.create方法:
通过表构造器的静态方法create自动在表中插入新的数据
该方法可以接收多个插入数据,最后的回调函数参数根据数据量决定
该方法支持两种调用:
- 错误优先的回调
- async await
const users = await User.create(
{ name: "1", email: "123@qq.com", passWord: "123" },
{ name: "2", email: "456@qq.com", passWord: "456" },
{ name: "3", email: "789@qq.com", passWord: "789" }
);
res.status(200).json(users); // users是数组
// 或者
User.create(
{ name: "str", email: "159@163.com", passWord: "159" },
{ name: "1", email: "123@qq.com", passWord: "123" },
{ name: "2", email: "456@qq.com", passWord: "456" },
{ name: "3", email: "789@qq.com", passWord: "789" },
(err, doc1, doc2, doc3) => {
if (err) {
return err;
}
res.status(200).json({ doc1, doc2, doc3 });
}
);
通过Model.insertMany方法
该方法与create的区别是它接收的第一个参数是数据组成的数组,多条数据只会插入第一条
const user = await User.insertMany({ name: "1", email: "123@qq.com", passWord: "123" });
const users = await User.insertMany([
{ name: "2", email: "456@qq.com", passWord: "456" },
{ name: "3", email: "789@qq.com", passWord: "789" },
]);
查
查找数据
通过Model.find方法
不传入参数会查找该表的所有数据
该方法返回值始终是数组
第一个参数
指定数据的某个键进行查找,键也能是正则表达式
const data = await User.find({ name: /\d/ });
限制查找范围,通过内置的字段限制某个字段的范围,$where函数参数来指定查询的限制范围
const data = await User.find({
name: { $gt: 1 },
$where: () => this.passWord == parseInt(this.email),
}); // 查找name大于1且密码和邮箱一样的
还能通过$and $or $not等参数来决定查找的范围
const data = await User.find({
$or: [{ $and: [{ name: /[1,2]/ }, { email: /(@qq.com)$/ }] }, { name: /\w+/ }],
}); // 查找 name为1或2且为QQ邮箱 或 name为字符串 的数据
如果查找的是对象中的属性用字符串做键或者嵌套查找
注意 嵌套查找必须顺序一致
// 查找这条数据 { name: "4", email: "357@163.com", passWord: "357", bio: { head: 123, foot: 789 } }
const datas = await User.find({ "bio.head": 123 }); // 字符串查找
const datas = await User.find({ bio: { head: 123, foot: 456 } }); // 嵌套对象查找 对象要写全且顺序不能改变,里面只能用具体的数据,不能用正则表达式或其它的限制
如果查找的是数组中的某项
// 有这两条数据 { name: "4", email: "357@163.com", passWord: "357", bio: [123, 456, "hahaha"] }
// { name: "5", email: "258@163.com", passWord: "258", bio: [123, 789, "haha"] }
const datas = await User.find({ bio: 123 }); // 如果数组中有一个数据符合就会找到 也能像上面一样用特殊参数指定范围
const datas = await User.find({ bio: { $all: [123, 456] } }); // 查找含有这两个值 只能找到第二条
const datas = await User.find({ bio: { $in: [456, 789] } }); // 查找这两个值中的任意一条 两条都能找到
const datas = await User.find({ "bio.1": { $gt: 456 } }); // 使用下标指明指定数据的范围 这里找到第二条
如果查找的是数组对象中的某项
// 有这两条数据
{
name: "4",
email: "357@163.com",
passWord: "357",
bio: [
{ head: 123, foot: 456 },
{ head: 456, foot: 789 },
],
},
{
name: "5",
email: "258@163.com",
passWord: "258",
bio: [
{ head: 123, foot: 789 },
{ head: 789, foot: 456 },
],
}
const datas = await User.find({ bio: { head: 123, foot: 789 } }); // 数组中含有这个对象就会找到,对象属性要写全,不能只写部分,循序不能修改
const datas = await User.find({ "bio.foot": 789 }); // 数组中只要有一个对象符合就会找到,这里两个都会找到
const datas = await User.find({
bio: { $elemMatch: { foot: 456, head: { $gt: 100 } } }, // 使用$elemMatch 数组中拥有指定的对象就会找到,可以交换顺序,可以使用限制,但是不能使用正则
});
第二个参数
限制返回数据含有的数据
const data = await User.find({ name: /\d/ }, { name: 1, email: 1, _id: 0 }); // _id默认带着,这里忽略了
第三个参数
可以使用keip limit sort来对查询结果进行操作
const data = await User.find({ name: /\d/ }, null, { skip: 1 }); // 这里只会查找到 2 3
第二三个参数也能用链式调用的方法定义
查询的结果支持链式调用,可以使用一些方法再对结果进行操作,相当于把第二个参数写道外面了
select:设置查询结果的数据包含哪些键 接收列明字符串组成的数组,如果字符串前加上-则是不显示const datas = await User.find().select(["name", "-_id"]); // 查询所有数据 返回对象只有name
limit:限制查找结果的长度skip:设置查找结果的起式位置sort:对查找结果排序 接收列名字符串,按照从小到大排序,如果前面加上-则会从大到小排const datas = await User.find().sort("-name"); // str 3 2 1
const datas = await User.find().sort("name"); // 1 2 3 str
count:返回查找结果的数量lean:将结果返回为普通的js对象而不是查询得到的Mongoose Documents类型对象
常用的内置字段:
| 字段 | 说明 |
|---|---|
| $or | 或关系 |
| $nor | 或关系取反 |
| $gt | 大于 |
| $gte | 大于等于 |
| $lt | 小于 |
| $lte | 小于等于 |
| $ne | 不等于 |
| $in | 在多个值范围内 |
| $nin | 不在多个值范围内 |
| $all | 匹配数组中多个值 |
| $regex | 正则,用于模糊查询 |
| $size | 匹配数组大小 |
| $maxDistance | 范围查询,距离(基于LBS) |
| $mod | 取模运算 |
| $near | 邻域查询,查询附近的位置(基于LBS) |
| $exists | 字段是否存在 |
| $elemMatch | 匹配内数组内的元素 |
| $within | 范围查询(基于LBS) |
| $box | 范围查询,矩形范围(基于LBS) |
| $center | 范围醒询,圆形范围(基于LBS) |
| $centerSphere | 范围查询,球形范围(基于LBS) |
| $slice | 查询字段集合中的元素(比如从第几个之后,第N到第M个元素 |
通过Model.findOne方法
该方法返回符合条件的第一条数据
通过Model.findById方法
通过每个数据的_id属性查询
删
通过Model.remove方法
不传入参数会删除该表的所有数据
该方法返回的是删除数据的条数,不会返回被删除数据
指定要删除数据的某个键,键也可以使用正则表达式
const remove = await User.remove({ name: /\d/ });
也可以先查找,然后用数据的remove方法
// 可以链式调用
const data = await User.find({ name: "1" }).remove();
// 也能迭代删除
const data = await User.find({ name: "2" });
data.forEach((item) => {
item.remove();
});
通过Model.findOneAndRemove方法
删除符合条件的第一条数据,并将这条数据返回
通过Model.findByIdAndRemove方法
通过_id删除
改
Model.update已经不支持
通过Model.updateOne Model.updateMany方法
该方法返回修改的信息,不是返回修改后的数据
先指定查询的条件,再在第二个参数放入修改的数据,第三个参数为一些设置
const datas = await User.updateOne({ name: "1" }, { $set: { name: "999" } }); // 将name为1的数据的name改为999
第三个参数如下,一般用不上
| 键名 | 默认值 | 说明 |
|---|---|---|
| safe | true | 安全模式 |
| upsert | false | 是没有这张表时是不是新建数据 |
| setDefaultsOnInsert | 如果upsert选项为true,在新建时插入文档定义的默认值 | |
| strict | 以strict模式进行更新 | |
| overwrite | false | 禁用update-only模式,允许覆盖记录 |
通过修改find findOne findById找到的数据后调用save方法
const data = await User.find({ name: "999" }); // data只会是一个数组 如果是findOne findById则不是
data.forEach((item) => {
item.name = "1";
item.save();
});
通过findOneAndUpdate findByIdAndUpdate方法
是上面的语法糖,获得修改后的数据
mogoose 创建数据库并增删改查的更多相关文章
- django之创建第8-1个项目-数据库之增删改查/数据库数据显示在html页面
1.为test.DB数据库预先创建下面数据 1 张三 16 2015-01-02 12 李四 17 2015-01-04 13 王五 14 ...
- 啊啊啊啊啊啊啊今天就写,炒鸡简单 数据库Sqlite的创建,库的增删改查
啦啦啦啦啦啦啦 写这个不用多长时间,我直接写代码注释都是些语句,Sql语句和Api来操作数据库 ,语句的参数我会注释 SQLite数据库创建数据库需要使用的api:SQLiteOpenHelper必须 ...
- Android学习---数据库的增删改查(sqlite CRUD)
上一篇文章介绍了sqlite数据库的创建,以及数据的访问,本文将主要介绍数据库的增删改查. 下面直接看代码: MyDBHelper.java(创建数据库,添加一列phone) package com. ...
- java jdbc 连接mysql数据库 实现增删改查
好久没有写博文了,写个简单的东西热热身,分享给大家. jdbc相信大家都不陌生,只要是个搞java的,最初接触j2ee的时候都是要学习这么个东西的,谁叫程序得和数据库打交道呢!而jdbc就是和数据库打 ...
- 【转载】通过JDBC对MySQL数据库的增删改查
通过JDBC进行简单的增删改查(以MySQL为例) 目录 前言:什么是JDBC 一.准备工作(一):MySQL安装配置和基础学习 二.准备工作(二):下载数据库对应的jar包并导入 三.JDBC基本操 ...
- MySQL数据库学习笔记(十二)----开源工具DbUtils的使用(数据库的增删改查)
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- Asp.net MVC4 使用EF实现数据库的增删改查
EF的使用 步骤: (1)将EF添加到项目:在Model右击添加新建项 找到ADO.NET实体数据模型,接着... (2)实现数据库的增删改查 查询 (因为在Model中已经添加EF实体了 ...
- 使用EF实现数据库的增删改查
EF的使用步骤:(1)将EF添加到项目:在Model右击添加新建项找到ADO.NET实体数据模型,接着…(2)实现数据库的增删改查查询(因为在Model中已经添加EF实体了,所以就可以在Control ...
- 开源工具DbUtils的使用(数据库的增删改查)
开源工具DbUtils的使用(数据库的增删改查) 一.DbUtils简介: DBUtils是apache下的一个小巧的JDBC轻量级封装的工具包,其最核心的特性是结果集的封装,可以直接将查询出来的结果 ...
随机推荐
- CNVD-2021-14536 锐捷 RG-UAC 统一上网行为管理审计系统信息泄露漏洞
漏洞简介 锐捷 RG-UAC 统一上网行为管理审计系统存在信息泄露,攻击者通过网页源代码可间接获取管理用户账号密码,登录管理后台. 漏洞复现 fofa搜索以下关键字 title="RG-UA ...
- one_gadget的一些姿势
概要 one_gadget是libc中存在的一些执行execve("/bin/sh", NULL, NULL)的片段,当可以泄露libc地址,并且可以知道libc版本的时候,可以使 ...
- ECDSA—模乘模块
如果a,b属于GF(P),则有乘法运算a*b=r (mod p), 其中r满足0<r<p-1,即a*b除以p的余数.该操作成为模p乘法.本模块输入两个数,完成两个数的模乘运算. 信号名 方 ...
- NOIP 模拟 $26\; \rm 神炎皇$
题解 \(by\;zj\varphi\) 一道 \(\varphi()\) 的题. 对于一个合法的数对,设它为 \((a*m,b*m)\) 则 \(((a+b)*m)|a*b*m^2\),所以 \(( ...
- DLL-创建DLL
动态链接库的创建 fangyukuan 2010.6.20 编写DLL时的函数与一般的函数方法基本一样.但要对库中的函数进行必要的声明,以说明哪些函数是可以导出的,哪些函数是不可以导出的. 把DLL中 ...
- mybatis面试题总结
1.什么是MyBatis? 答:MyBatis是一个可以自定义SQL.存储过程和高级映射的持久层框架. 2.讲下MyBatis的缓存 答:MyBatis的缓存分为一级缓存和二级缓存,一级缓存放在ses ...
- air530GPS数据通过air202上传阿里云
写硬件博客真是太难了 GPS/北斗 导航模块 Air530开发板G1学习日记 上面这个博客详细介绍了如何测试使用Air530模块根据稳重[Air530 和Air 202 进行配合使用,实现2G GPR ...
- SpringCloud 商品架构例子(一)
架构演进和分布式系统基础知识 1.传统架构演进到分布式架构 简介:讲解单机应用和分布式应用架构演进基础知识 高可用 LVS+keepalive 单体应用: 集群: 微服务架构: 1.单体应用: 开发速 ...
- Ubuntu防火墙:ufw
原始linux的防火墙是iptables,以为过于繁琐,各个发行版几乎都有自己的方案; ubuntu下的防火墙是ufw[ubuntu fireward的缩写],centos的防火墙是fireward ...
- JDBC中级篇(MYSQL)——模拟从数据库中上传下载附件
注意:其中的JdbcUtil是我自定义的连接工具类:代码例子链接: package b_blob_clob; import java.io.BufferedOutputStream; import j ...