ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

mongoose入门以及mongoose实现数据的增删改查(有代码简单易上手)

mongoose入门以及mongoose实现数据的增删改查(有代码简单易上手) 1. 从零理解 mongoose它到底解决了什么问题如果你刚开始学 Node.js直接拿官方 mongodb 驱动去写增删改查大概率会被一堆回调、字段校验、集合名拼写搞晕。mongoose 就是在这个场景下出现的它是 MongoDB 的 ODM对象文档映射工具把「文档」映射成「对象」让你用写类的方式去操作数据库。简单说mongodb 驱动给你的是「原始 SQL 感」mongoose 给你的是「带类型和校验的模型感」。它能做什么定义 Schema 约束字段类型、给字段设默认值和必填、基于 Model 直接调用 save/find/updateOne/deleteOne、支持链式查询和 Promise。适合谁适合正在学 Node.js、想快速把数据存进 MongoDB、又不想手写一堆校验逻辑的初学者。我试过在没 Schema 的情况下直接插数据结果同一个集合里有的文档 price 是字符串、有的是数字查询时各种类型不匹配排查半天——这就是 Schema 存在的意义。这篇会带你从本地连接开始一步步定义 Schema、创建 Model然后把增删改查四类操作全部跑通。每一步都有可复制的代码和运行验证方式你跟着敲就能看到结果。过程中如果遇到模型调用报错、连接超时这类问题我也会在排障章节里给出定位思路。对于需要长期跑脚本或做 Agent 编码的场景后面也会提到怎么把模型调用统一管理起来避免每个文件都重复写连接配置。2. 环境准备与 TaoToken 前置配置在写 mongoose 代码之前先把本地环境和模型调用入口理清楚。mongoose 本身只负责数据库操作但你在调试 CRUD 时经常需要对照模型输出、排查字段类型这时候有一个统一的模型对话入口会方便很多。TaoToken 提供模型对话、Coding Plan、API Keys 和接入文档几个入口下面按用途分开说。2.1 本地 MongoDB 与 Node.js 检查先确认本机 MongoDB 服务已经启动默认端口 27017。终端执行mongod --version node -v npm -v如果 mongod 没启动用系统服务方式拉起即可。Node.js 建议 16 以上mongoose 8.x 对 Node 版本有要求太低会报语法错误。2.2 TaoToken 入口按场景选择模型对话入口适合你在写 Schema 时快速问「这个字段类型该怎么写」或者把报错信息贴进去让它帮你定位。地址是 https://taotoken.net/api 对话页在 deep link 里对应模型对话路径。如果你要长期跑编码任务、写 Agent 脚本Coding Plan 更合适能统一管理调用额度。API Keys 页面用来生成和管理密钥接入文档里有各语言的最小示例。注意API Keys 属于敏感信息不要写进前端代码或提交到公开仓库。建议放在.env文件里用dotenv读取。2.3 项目初始化新建一个文件夹名字不要叫 mongoose否则 npm 安装时会和包名冲突。进入目录后执行npm init --yes npm install mongoose --save npm install dotenv --savenpm init --yes生成 package.json--save把依赖写进 dependencies。装完后目录里应该有 node_modules 和 package.json。3. 可复制配置连接、Schema 与 Model这一章是核心把连接配置、Schema 骨架、Model 创建全部写成可直接复制的代码。建议按文件拆分连接单独一个文件业务操作单独一个文件避免每次改 CRUD 都要动连接代码。3.1 数据库连接文件 conndb.js// conndb.js const mongoose require(mongoose); const MONGO_URI process.env.MONGO_URI || mongodb://127.0.0.1:27017/may; mongoose.connect(MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true, }); const db mongoose.connection; db.on(error, (err) { console.log(连接失败!!!, err.message); }); db.once(open, () { console.log(连接成功~~~); }); module.exports mongoose;参数一mongodb://127.0.0.1:27017/may是连接地址格式为协议://IP:端口/数据库名。参数二的两个选项用于新版解析器和拓扑发现避免启动时告警。参数三是通过事件监听处理连接结果比回调更清晰。导出 mongoose 实例其他文件 require 后就能直接用 Schema 和 model。运行验证node conndb.js终端出现「连接成功~~~」说明数据库通了。如果卡住不动检查 mongod 是否启动、端口是否被占用。3.2 Schema 定义字段类型与约束Schema 相当于表结构在 Node.js 里就是一份字段声明。新建 fruits.js// fruits.js const db require(./conndb); const fruitSchema new db.Schema({ name: { type: String, required: true }, price: { type: Number, min: 0 }, origin: { type: String, default: 未知 }, createdAt: { type: Date, default: Date.now }, }); const fruitModel db.model(fruits, fruitSchema); module.exports fruitModel;required: true表示必填min: 0限制价格不能为负default给默认值。Schema 通过限制输入字段类型来定义 documents 的基本结构。Model 才是操作数据库最直接的一层所有 CRUD 都围绕 Model 展开。3.3 Model 创建与实例化db.model(fruits, fruitSchema)两个参数集合名和 Schema。mongoose 会自动把集合名转成小写复数所以这里对应数据库里的 fruits 集合。实例化用new fruitModel(object)相当于把内存里的数据对象准备好调用 save 才会真正写入硬盘。const fruitEntity new fruitModel({ name: 苹果, price: 10 }); fruitEntity.save((err, data) { if (!err) { console.log(添加成功); console.log(data); } });4. 增删改查完整实现与验证下面把四类操作拆开写每段都可以单独跑。注意每次修改 fruits.js 后都要在终端重新执行node fruits.jsNode 不会热更新。4.1 增加数据save、create、insertMany// 单条保存 const apple new fruitModel({ name: 苹果, price: 10 }); apple.save().then((data) { console.log(save 成功, data); }); // create 直接创建 fruitModel.create({ name: 香蕉, price: 6 }).then((data) { console.log(create 成功, data); }); // 批量插入 fruitModel.insertMany([ { name: 梨, price: 8 }, { name: 柠檬, price: 5 }, ]).then((data) { console.log(insertMany 成功, data.length); });save 是实例方法create 和 insertMany 是 Model 静态方法。批量插入返回数组适合初始化测试数据。4.2 更新数据updateOne 与 updateManyfruitModel.updateOne( { name: 香蕉 }, { $set: { name: 梨 } } ).then((data) { console.log(data); console.log(更新成功); }, (err) { console.log(更新失败, err.message); });updateOne改一条updateMany改多条。$set是更新操作符只改指定字段。返回结果里matchedCount和modifiedCount能看出是否命中。4.3 查询数据find、findOne、条件与去重// 查询全部 fruitModel.find().then((data) { console.log(data); console.log(查询成功); }); // 按条件查询 fruitModel.find({ name: 柠檬 }).then((data) { console.log(data); }); // 查询一条 fruitModel.findOne({ name: 柠檬 }).then((data) { console.log(data); }); // 条件查询$lt 小于、$lte 小于等于、$gt 大于、$gte 大于等于、$ne 不等于 fruitModel.find({ price: { $ne: 10 } }).then((data) { console.log(data); }); // 去重 fruitModel.distinct(name).then((data) { console.log(data); }); // or 查询 fruitModel.find({ $or: [{ name: 柠檬 }, { name: 梨 }] }).then((data) { console.log(data); }); // limit 限制条数、skip 跳过条数 fruitModel.find().limit(4).then((data) { console.log(data); }); fruitModel.find().skip(3).then((data) { console.log(data); });条件操作符用对象包裹字段$or接收数组。limit 和 skip 常配合做分页skip 的值是跳过多少条。4.4 删除数据deleteOne、deleteMany 与 remove// 条件删除 fruitModel.deleteOne({ name: 苹果 }).then((data) { console.log(data); console.log(deleteOne 成功); }); // 删除多条 fruitModel.deleteMany({ price: { $lt: 6 } }).then((data) { console.log(data.deletedCount); }); // remove 不传条件会删除全部慎用 fruitModel.remove({ name: 梨 }).then((data) { console.log(remove 成功, data); });remove()不传条件会清空集合测试环境用可以生产环境一定要加条件。新版 mongoose 推荐 deleteOne/deleteManyremove 已标记废弃但仍可用。4.5 运行验证与结果对照把上面任意一段放进 fruits.js终端执行node fruits.js看到「添加成功」「查询成功」这类输出并且打印出文档对象就说明链路通了。可以用 MongoDB Compass 或mongosh连上去看集合里的数据是否一致。如果输出是空数组先确认插入操作是否真的执行过再检查集合名是否匹配。5. 本篇常见错误排查5.1 连接超时或 ECONNREFUSED报错connect ECONNREFUSED 127.0.0.1:27017说明本机 MongoDB 没启动或端口不对。先执行mongod --version确认安装再检查服务是否运行。如果用了远程地址确认网络可达和端口开放。5.2 Schema 字段类型不匹配插入时传了字符串给 Number 字段mongoose 会尝试转换转不了就报 ValidationError。排查时把报错里的path字段找出来对照 Schema 定义检查。开启runValidators: true能让更新时也走校验。5.3 Model 重复定义报错OverwriteModelError: Cannot overwrite fruits model once compiled.原因是同一个进程里多次调用db.model(fruits, schema)。解决办法是用db.models.fruits || db.model(fruits, schema)判断或者把 Model 定义单独放一个文件只 require 一次。5.4 查询返回空数组先确认集合里确实有数据用mongosh执行db.fruits.find()看一眼。再检查查询条件字段名和大小写MongoDB 字段名区分大小写。如果用了 skip 且值大于总数也会返回空。5.5 回调与 Promise 混用导致无输出mongoose 支持回调和 Promise但不要在同一段逻辑里混着写。如果用了.then()又传了回调可能只走其中一条路径。统一用 async/await 或统一用 then排查时加console.log确认走到哪一步。6. 把模型调用统一管理起来mongoose 的 CRUD 跑通之后你会发现调试阶段经常需要对照模型输出、让模型帮你解释报错。如果每个脚本都单独配一套调用密钥和额度管理会很乱。TaoToken 的 API Keys 页面可以生成统一密钥接入文档里有 Node.js 的最小调用示例直接复制就能用。模型对话入口适合临时问字段类型和报错定位Coding Plan 适合长期跑编码任务和 Agent 脚本。具体操作上先在 API Keys 页面创建密钥写进.envTAOTOKEN_API_KEY你的密钥然后在需要的地方用process.env.TAOTOKEN_API_KEY读取。接入文档地址是 https://taotoken.net/api 里面有各语言的请求格式。如果你在写 mongoose 的批量脚本时需要模型辅助生成测试数据可以把 Schema 贴进模型对话让它按字段类型生成一批符合约束的 JSON再喂给 insertMany比手写快很多。最后提醒一句mongoose 的 Schema 一旦定义后续改字段类型要同步迁移已有数据否则查询时会出现类型不一致的脏数据。测试阶段可以放心删库重来生产环境记得先备份。
返回列表