【Nodejs】操作mongodb数据库

1.简介
- Mongoose是一个让我们可以通过Node来操作MongoDB的模块。
- Mongoose是一个对象文档模型(ODM)库,它对Node原生的MongoDB模块进行了进一步的优化封装,并提供了更多的功能。在大多数情况下,它被用来把结构化的模式应用到一个MongoDB集合,并提供了验证和类型转换等好处
- mongoose中的对象:
- Schema 模式对象(Schema对象定义约束了数据库中的文档结构)
- Model 模型对象(Model对象作为集合中的所有文档的表示,相当于MongoDB数据库中的集合collection)
- Document 文档对象(Document表示集合中的具体文档,相当于集合中的一个具体的文档)
mongoose的好处
- 可以为文档创建一个模式结构(Schema)
- 可以对模型中的对象/文档进行验证
- 数据可以通过类型转换转换为对象模型
- 可以使用中间件来应用业务逻辑挂钩
- 比Node原生的MongoDB驱动更容易
安装
npm i -S mongoose
2.连接数据库
config/db.config.js
// 1.引入mongoose
const mongoose = require("mongoose");// 2.连接mongodb数据库
// 指定连接数据库后不需要存在,当你插入第一条数据库后会自动创建数据库
/*
mongoose.connect('mongodb://数据库地址:端口号/数据库名',{useMongoClient:true})
如果端口号是默认端口号(27017)则可以省略不写
*/
mongoose.connect('mongodb://127.0.0.1:27017/ds2', {useNewUrlParser: true,useUnifiedTopology: true,useCreateIndex: true,
})// 3.监听mongodb数据库的连接状态
// 绑定数据库连接成功事件
mongoose.connection.once("open", function () {console.log("连接成功");
});
// 绑定数据库连接失败事件
mongoose.connection.once("close", function () {console.log("数据库连接已经断开");
});// 4.断开数据库连接(一般不用)
mongooes.disconnect();
注:MongoDB数据库,一般情况下,只需要连接一次,连接一次后,除非项目停止服务器关闭,否则连接一般不会断开
在bin目录下的www文件中使用直接require(“…/config/db.config.js”)进行数据库连接的启动

3.创建模式对象和模型对象
数据库中的 Schema,为数据库对象的集合。schema 是 mongoose 里会用到的一种数据模式,可以理解为表结构的定义;每个 schema会映射到 mongodb 中的一个 collection,它不具备操作数据库的能力。
- 每个 schema 都会映射到一个 MongoDB collection 并定义这个collection里的文档结构
- 支持的字段类型
| 类型 | 作用 |
|---|---|
| String | 定义字符串 |
| Number | 定义数字 |
| Date | 定义日期 |
| Buffer | 定义二进制 |
| Boolean | 定义布尔值 |
| Mixed | 定义混合类型 |
| ObjectId | 定义对象ID |
| Array | 定义数组 |
model/UserModel.js
const mongoose = require("mongoose")
const Schema=mongooes.Schema;
//创建模式对象
const UserType=new Schema({name:{type: 'string',//添加约束,保证数据的完整性,让数据按规矩统一require: true},age:Number,gender:{type:String,// 默认值default:'female'},address:String
})//创建模型对象
//通过Schema来创建Model
//Model代表的是数据库中的集合,通过Model才能对数据库进行操作
//mongoose.model(modelName,schema)
//建立映射关系,students是集合,mongoose会自动将集合变成复数比如student会变成students
//大写也会被自动转换为小写,比如Users会变成users
const UserModel=mongoose.model("UserModel",UserType,"user");
//第一个参数表示创建的集合的名称,第二个参数表示利用的模式对象,第三个参数是强行指定集合名称module.exports = UserModel
4.文档新增
4.1 save()
操作的是文档
案例:
var mongoose = require('mongoose')
const UserModel = require('../model/UserModel');//链式调用 通过new 一个Model创建一个 document
new UserModel({name:"小明",age:18}).save((err,docs) => {if(!err){console.log(docs)res.send({code: 200,data: {id: docs._id,},})//{ _id: 6017bd1cf4cc8544d8ed2a8a, name: '小明', age: 18, __v: 0 }}
})
4.2 create()
- 操作模型
Model.create(doc(s), [callback])- 参数:
[doc(s)]:文档对象或文档对象数组
[callback]:回调函数
var mongoose = require('mongoose')
const UserModel = require('../model/UserModel');UserModel.create({name:"小明",age:18},{name:"小红",age:10},(err,doc1,doc2) => {if(!err){console.log(doc1)//{ _id: 6017be2d77c8dd01242624bb, name: '小明', age: 18, __v: 0 }console.log(doc2)//{ _id: 6017be2d77c8dd01242624bc, name: '小红', age: 10, __v: 0 }}
})
其它:
//Model.createOne(doc, [callback]); 创建一个对象
//Model.createMany(doc, [callback]); 创建多个对象
// -doc是需要插入的文档
// -callback(err) 是回调函数,可以用来提示是否创建成功了
4.3 insertMany()
Model.insertMany(doc(s), [options], [callback])
返回值为一个数组
案例:
UserModel.insertMany({name:"小明",age:18},{name:"小芳",age:14},(err,docs) => {if(!err){console.log(docs)/*[{ _id: 6017befb5c36d64d08b72576, name: '小明', grades: 68, __v: 0 },{ _id: 6017befb5c36d64d08b72577, name: '小芳', grades: 94, __v: 0 }]*/}
})
5.文档查询
| _id | name | grades | __v |
|---|---|---|---|
| 6017befb5c36d64d08b72576 | 小明 | 68 | 0 |
| 6017befb5c36d64d08b72577 | 小芳 | 94 | 0 |
| 6017c455ba09d355a49ec8eb | 小红 | 52 | 0 |
| 6017c455ba09d355a49ec8ec | 小刚 | 46 | 0 |
5.1 find()
-
Model.find(conditions, [projection], [options], [callback]) -
参数
- conditions:查询条件
- [projection]:控制返回字段
- [options]:配置查询参数
- [callback]:回调函数–function(err,docs){}
-
案例:
var mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student',(err) => {if(!err){var schema = new mongoose.Schema({name:String,grades:Number})var stuModel = mongoose.model('grades',schema)//查询所有数据stuModel.find((err,docs) => {if(!err){console.log(docs)}}) /* [{ _id: 6017befb5c36d64d08b72576, name: '小明', grades: 68, __v: 0 },{ _id: 6017befb5c36d64d08b72577, name: '小芳', grades: 94, __v: 0 },{ _id: 6017c455ba09d355a49ec8eb, name: '小红', grades: 52, __v: 0 },{ _id: 6017c455ba09d355a49ec8ec, name: '小刚', grades: 46, __v: 0 }]*///查询成绩大于60以上的数据stuModel.find({grades:{$gte:60}},(err,docs) => {if(!err){console.log(docs)}})/*[{ _id: 6017befb5c36d64d08b72576, name: '小明', grades: 68, __v: 0 },{ _id: 6017befb5c36d64d08b72577, name: '小芳', grades: 94, __v: 0 }]*///查询成绩大于60以上且名字里存在‘芳’的数据stuModel.find({name:/芳/,grades:{$gte:60}},(err,docs) => {if(!err){console.log(docs)}})/*[* { _id: 6017befb5c36d64d08b72577, name: '小芳', grades: 94, __v: 0 }* ]*///查询名字里存在‘明’的数据且只输出‘name’字段//_id默认会返回stuModel.find({name:/明/},{name:1,_id:0},(err,docs) => {if(!err){console.log(docs)}})// [{name: '小明'}]//跳过前两条数据并限制只输出一条数据stuModel.find(null,null,{skip:2,limit: 1},(err,docs) => {if(!err){console.log(docs)}})/*[{ _id: 6017c455ba09d355a49ec8eb, name: '小红', grades: 52, __v: 0 }*/}
})
5.2 findById()
Model.findById(id, [projection], [options], [callback])- 案例:
var mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student',(err) => {if(!err){var schema = new mongoose.Schema({name:String,grades:Number})var stuModel = mongoose.model('grades',schema)//保存查询数据的_idvar aIDArr = []//查询所有数据stuModel.find((err,docs) => {if(!err){docs.forEach((item,index,arr)=>{aIDArr.push(item._id)})//显示第 0 个元素的所有字段stuModel.findById(aIDArr[0],(err,doc)=>{if(!err){console.log(doc)}})// { _id: 6017befb5c36d64d08b72576, name: '小明', grades: 68, __v: 0 }//显示第 0 个元素且只输出name字段stuModel.findById(aIDArr[0],{name:1,_id:0},(err,doc)=>{if(!err){console.log(doc)}})// { name: '小明' }//显示第 0 个元素且输出最少的字段(_id默认输出)stuModel.findById(aIDArr[0],{lean:true},(err,doc)=>{if(!err){console.log(doc)}})// { _id: 6017befb5c36d64d08b72576 }}})}
})
5.3 findOne()
- 返回查询到的数据的第一个
Model.findOne([conditions], [projection], [options], [callback])- 案例:
var mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student',(err) => {if(!err){var schema = new mongoose.Schema({name:String,grades:Number})var stuModel = mongoose.model('grades',schema)//找出age>80的文档中的第一个文档stuModel.findOne({grades:{$gt:80}},(err,doc) => {if(!err){console.log(doc)}})//{ _id: 6017befb5c36d64d08b72577, name: '小芳', grades: 94, __v: 0 }//找出age>80的文档中的第一个文档,且只输出name字段stuModel.findOne({grades:{$gt:80}},{name:1,_id:0},(err,doc) => {if(!err){console.log(doc)}})//{ name: '小芳' }//找出age>80的文档中的第一个文档,且输出包含name字段在内的最短字段stuModel.findOne({grades:{$gt:80}},{lern:true},(err,doc) => {if(!err){console.log(doc)}})//{ _id: 6017befb5c36d64d08b72577 }}
})
5.4 复杂查询【$where】
- $where 可以使用任意的 JavaScript 作为查询的一部分,包含JavaScript 表达式的字符串或者函数
- 案例
var mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student',(err) => {if(!err){var schema = new mongoose.Schema({name:String,grades:Number})//添加一个测试字段// schema.add({test:Number})var stuModel = mongoose.model('grades',schema)//添加两条数据// stuModel.create({name:"小花",grades:76,test:76},{name:"小兰",grades:60,test:30},(err,docs)=>{// console.log(docs)// })//字符串 es5中this与obj指向一样,es6中只能用objstuModel.find({$where:"this.grades == this.test" || "obj.grades == obj.test"},(err,doc) => {if(!err){console.log(doc)}})//[{_id: 6017d7cb8a95cb2a00aae3ae,name: '小花',grades: 76,test: 76,__v: 0}]//函数stuModel.find({$where:function() {return this.grades == this.test || obj.grades == obj.test*2}},(err,doc) => {if(!err){console.log(doc)}})/*[{_id: 6017d7cb8a95cb2a00aae3ae,name: '小花',grades: 76,test: 76,__v: 0},{_id: 6017d7cb8a95cb2a00aae3af,name: '小兰',grades: 60,test: 30,__v: 0}]*/}
})
5.5 常用查询条件
$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个元素
5.6 特定类型查询
| _id | name | grades | __v | test |
|---|---|---|---|---|
| 6017befb5c36d64d08b72576 | 小明 | 68 | 0 | 1 |
| 6017befb5c36d64d08b72577 | 小芳 | 94 | 0 | 3 |
| 6017c455ba09d355a49ec8eb | 小红 | 52 | 0 | 5 |
| 6017c455ba09d355a49ec8ec | 小刚 | 46 | 0 | 2 |
| 6017d7cb8a95cb2a00aae3ae | 小花 | 76 | 0 | 4 |
| 6017d7cb8a95cb2a00aae3af | 小兰 | 60 | 0 | 6 |
方法
| 方法 | 作用 |
|---|---|
| sort | 排序 |
| skip | 跳过 |
| limit | 限制 |
| select | 显示字段 |
| exect | 执行 |
| count | 计数 |
| distinct | 去重 |
exec()和 then()
两者返回的都是 promise对象 exec一般用于独立的动作一次性执行, then则用于连续性的动作 从其方法名也可以区别它们的用法,exec就是执行的意思,then就是然后怎么怎么, exec和then的参数是有所不同的,前者是 callback(err,doc),后者则是 resolved(doc),rejected(err)
案例:
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student')
var Schema =new mongoose.Schema({ name:String,grades:Number,test:{type:Number,default:0}})
var stuModel = mongoose.model('grades', Schema);// 按test从小到大排序
// 1是升序,-1是降序
stuModel.find().sort({test:1}).exec((err,docs)=>{console.log(docs)
})
// 按test从大到小排列
stuModel.find().sort('-test').exec((err,docs)=>{console.log(docs)
})
// 跳过1个,显示其他
stuModel.find().skip(1).exec((err,docs)=>{console.log(docs)
})
// 显示2个
stuModel.find().limit(2).exec((err,docs)=>{console.log(docs)
})
// 显示name、grades字段,不显示id字段
stuModel.find().select('name grades -id').exec((err,docs)=>{console.log(docs)
})
// 跳过第1个后,只显示2个数据,按照grades由大到小排序,且不显示id字段
stuModel.find().skip(1).limit(2).sort('-grades').select('-id').exec((err,docs)=>{console.log(docs)/[{ name: '小明', grades: 78, v: 0, test: 1 },{ name: '小花', grades: 76, test: 4, v: 0 }]/
})
// 显示集合stuModel中的文档数量
stuModel.find().count((err,count)=>{console.log(count)//6
})
// 返回集合stuModel中的grades的值
stuModel.find().distinct('grades',(err,distinct)=>{console.log(distinct)//[ 46, 52, 60, 76, 78, 94 ]
})
6.文档更新
6.1 update()
Model.update(conditions, doc, [options], [callback])- 参数
- conditions:查询条件
- doc:需要修改的数据(插入的数据)
- [options]:控制选项
safe (boolean): 默认为true。安全模式。 upsert (boolean): 默认为false。如果不存在则创建新记录。 multi (boolean): 默认为false。是否更新多个查询记录。 runValidators: 如果值为true,执行Validation验证。 setDefaultsOnInsert: 如果upsert选项为true,在新建时插入文档定义的默认值。 strict (boolean): 以strict模式进行更新。 overwrite (boolean): 默认为false。禁用update-only模式,允许覆盖记录。
- [callback]:回调函数
- 若设置了查询条件,当数据库不满足时默认什么也不发生
- update() 方法中的回调函数不能省略,否则数据不会更新,当回调无有用信息时可以使用exec()简化
stuModel.update({name:'小明'},{$set:{test:34}}.exec())
案例
//第一步,引入mongoose
const mongoose = require('mongoose')
//第二步,连接数据库
mongoose.connect('mongodb://localhost:27017/student',err=>{if(!err){//第三步,创建模板var Schema =new mongoose.Schema({ name:String,grades:Number,test:{type:Number,default:0}})// var Schema = new Schema()//第四步,将模板映射到集合并创建var stuModel = mongoose.model('grades',Schema)//查询name为小明的数据,并将其test更改为34//若有多个文档,默认只更新第一个stuModel.update({name:'小明'},{$set:{test:34}},(err,raw)=>{console.log(raw)})//{ n: 1, nModified: 1, ok: 1 }//6017befb5c36d64d08b72576 小明 68 0 34}
})
6.2 updateOne()
Model.updateOne(conditions, doc, [options], [callback])- 与update()相似,唯一区别为updateOne() 默认更新一个文档,即使设置{multi:true}也无法只更新一个文档
6.3 updateMany()
Model.updateMany(conditions, doc, [options], [callback])- 与update()相似,唯一区别为updateMany() 默认更新多个文档,即使设置{multi:false}也无法只更新一个文档
6.4 find()+save()
用于复杂更新
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student',err=>{if(!err){var Schema =new mongoose.Schema({ name:String,grades:Number,test:{type:Number,default:0}})var stuModel = mongoose.model('grades',Schema)//查询成绩小于60的数据,并在其名字后添加‘:差生’字段stuModel.find({grades:{$lt:60}},(err,docs)=>{console.log(docs);/*[{test: 0,_id: 6017c455ba09d355a49ec8eb,name: '小红',grades: 52,__v: 0},{test: 0,_id: 6017c455ba09d355a49ec8ec,name: '小刚',grades: 46,__v: 0}]*/docs.forEach((item,index,arr) => {item.name += ':差生'//将修改后的数据保存item.save()})console.log(docs)/*[{test: 0,_id: 6017c455ba09d355a49ec8eb,name: '小红:差生',grades: 52,__v: 0},{test: 0,_id: 6017c455ba09d355a49ec8ec,name: '小刚:差生',grades: 46,__v: 0}]*/})}
})
6.5 findOne() + save()
- 用于复杂更新
- findOne()返回值为文档对象
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student',err=>{if(!err){var Schema =new mongoose.Schema({ name:String,grades:Number,test:{type:Number,default:0}})var stuModel = mongoose.model('grades',Schema)//查询成绩小于60的数据,并在其名字后添加‘:差生’字段stuModel.findOne({name:'小明'},(err,doc)=>{console.log(doc);//{test: 34,_id: 6017c455ba09d355a49ec8eb,name: '小明',grades: 68,__v: 0},doc.age += 10doc.save()console.log(docs)//{test: 34,_id: 6017c455ba09d355a49ec8eb,name: '小明',grades: 78,__v: 0}})}
})
6.6 fingOneAndUpdate()
Model.findOneAndUpdate([conditions], [update], [options], [callback])
6.7 findByIdAndUpdate()
Model.findByIdAndUpdate([conditions], [update], [options], [callback])
7.文档删除
7.1 deleteOne()
- 会删除符合条件的所有数据
- Model的deleteOne()
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student',err=>{if(!err){var Schema =new mongoose.Schema({ name:String,grades:Number,test:{type:Number,default:0}})var stuModel = mongoose.model('grades',Schema)//删除名字中包含‘差生’的数据stuModel.deleteOne({name:/差生/},function(err){})// 回调函数不能省略,但可以使用exec() 简写//stuModel.deleteOne({name:/差生/}).exec()})}
})
- 文档的deleteOne()
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student',err=>{if(!err){var Schema =new mongoose.Schema({ name:String,grades:Number,test:{type:Number,default:0}})var stuModel = mongoose.model('grades',Schema)//删除名字中包含‘差生’的数据stuModel.find({name:/差生/},function(err,docs){docs.forEach((item,index,arr)=>{item.deleteOne((err,doc)=>{//doc为被删除的值console.log(doc)})})})})}
})
7.2 findOneAndRemove()
- 删除符合条件的一条数据
- Model.findOneAndRemove(conditions, [options], [callback])
- 回调不可省略,但可以使用exec() 简写
stuModel.findOneAndRemove({name:/差生/}).exec()
7.3 findByIdAndRemove()
- 通过id删除数据(id是唯一的)
- Model.findByIdAndRemove(conditions, [options], [callback])
- 回调不可省略,但可以使用exec() 简写
8.前后钩子
- 前后钩子即 pre() 和 post() 方法(中间件)
- 中间件在schema上指定,类似静态方法或实例方法等
- 可以在执行以下操作时设置前后钩子
init validate save remove count find findOne findOneAndRemove findOneAndUpdate insertMany update
-
【pre()】:在执行某些操作前执行
-
【post】:在执行某些操作前后执行,不可以使用next()
案例:
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student')
var Schema =new mongoose.Schema({ name:String,grades:Number,test:{type:Number,default:0}})
Schema.pre('find',function(next){console.log('我是pre方法1');next();
});
Schema.pre('find',function(next){console.log('我是pre方法2');next();
});
Schema.post('find',function(docs){console.log('我是post方法1');
});
Schema.post('find',function(docs){console.log('我是post方法2');
});
var stuModel = mongoose.model('grades', Schema);
stuModel.find(function(err,docs){console.log(docs[0]);
})
/*
我是pre方法1
我是pre方法2
我是post方法1
我是post方法2
{test: 34, _id: 6017befb5c36d64d08b72576,name: '小明',grades: 78,__v: 0}
*/
9.文档验证
- 保证保存文档时,可以按照Schema设置的字段进行设置
9.1 【required】:数据必填
//将name设置为必填字段,如果没有name字段,文档将不被保存,且出现错误提示
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student')
var Schema =new mongoose.Schema({name:{type:String,required:true},age:Number
})
var stuModel = mongoose.model('students', Schema);
new stuModel({age:20}).save((err,doc)=>{if(err){return console.log(err)}console.log(doc)
})//报错:name: Path `name` is required.
9.2 【default】:默认值
//设置age字段的默认值为18,如果不设置age字段,则会取默认值
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student')
var Schema =new mongoose.Schema({name:String,age:{type:Number,default:18}
})
var stuModel = mongoose.model('students', Schema);
new stuModel({name:'李雷'}).save((err,doc)=>{if(err){return console.log(err)}console.log(doc)
})//{ age: 18, _id: 6018f3bd7e51343e6c4f212b, name: '李雷', __v: 0 }
9.3 【min】【max】:最小/大值
- 只适用于数字
//将age的取值范围设置为[0,10]。如果age取值为20,文档将不被保存,且出现错误提示
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student')
var Schema =new mongoose.Schema({name:String,age:{type:Number,min:10,max:18}
})
var stuModel = mongoose.model('students', Schema);
new stuModel({name:'李雷',age:20}).save((err,doc)=>{if(err){return console.log(err)}console.log(doc)
})//age: Path `age` (20) is more than maximum allowed value (18).
9.4 【match】:正则匹配
- 只适用于字符串
//将name的match设置为必须存在'01'字符。如果name不存在'01',文档将不被保存,且出现错误提示
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student')
var Schema =new mongoose.Schema({name:{type:String,match:/01/},age:Number,
})
var stuModel = mongoose.model('students', Schema);
new stuModel({name:'李雷',age:20}).save((err,doc)=>{if(err){return console.log(err)}console.log(doc)
})//name: Path `name` is invalid (李雷).
9.5【enum】:枚举匹配
- 只适用于字符串
//将name的枚举取值设置为['zs','ls','ww'],如果name不在枚举范围内取值,文档将不被保存,且出现错误提示
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student')
var Schema =new mongoose.Schema({name:{type:String,enum:['zs','ls','ww']},age:Number,
})
var stuModel = mongoose.model('students', Schema);
new stuModel({name:'lss',age:20}).save((err,doc)=>{if(err){return console.log(err)}console.log(doc)
})//name: ValidatorError: `lss` is not a valid enum value for path `name`.
9.6 【validate】:自定义匹配
- validate实际上是一个函数,函数的参数代表当前字段,返回true表示通过验证,返回false表示未通过验证
//定义名字name的长度必须在4个字符以上
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student')
var Schema =new mongoose.Schema({name:{type:String,validate:nameLength},age:Number,
})
var stuModel = mongoose.model('students', Schema);
new stuModel({name:'abcd',age:20}).save((err,doc)=>{if(err){return console.log(err)}console.log(doc)
})function nameLength(arg){if(arg.length>4){return true}return false
}//name: Validator failed for path `name` with value `abcd`
相关文章:
【Nodejs】操作mongodb数据库
1.简介 Mongoose是一个让我们可以通过Node来操作MongoDB的模块。Mongoose是一个对象文档模型(ODM)库,它对Node原生的MongoDB模块进行了进一步的优化封装,并提供了更多的功能。在大多数情况下,它被用来把结构化的模式应用到一个MongoDB集合,并…...
SQL-每日一题【619.只出现一次的最大数字】
题目 MyNumbers 表: 单一数字 是在 MyNumbers 表中只出现一次的数字。 请你编写一个 SQL 查询来报告最大的 单一数字 。如果不存在 单一数字 ,查询需报告 null 。 查询结果如下例所示。 示例 1: 示例 2: 解题思路 1.题目要求我…...
紫光FPGA试用--软件篇
目录 一 软件安装启动 二 如何打开IP核?查看/修改现有IP核参数? 三 如何定义引脚? 四 如何下载code进入FPGA? 1. 下载到FPGA芯片内: 2.下载到外部FLASH中 五 如何进入在线调试模式,调试步骤 操作步骤ÿ…...
PDF添加水印以及防止被删除、防止编辑与打印
方法记录如下: 1、添加水印; 2、打印输出成一个新的pdf; 3、将pdf页面输出成一张张的图片:(福昕pdf操作步骤如下) 4、将图片组装成一个新的pdf:(福昕pdf操作步骤如下)…...
el-tree转换为表格样式的记录2
上一篇文章记录的是自己将树状数据转换为表格形式。但是出现了一个小bug,点击子节点时候会选中父节点,这个是正常需求没问题。但是我点击父节点时候取消所有子节点,父节点 选择也会失去,这是我不想要执行的。例如一个页面里面有主…...
MS1826B HDMI 1进4出 视频拼接芯片
MS1826B 是一款多功能视频处理器,包含 4 路独立 HDMI 音视频输出通道、1 路 HDMI 音视 频输入通道以及 1 路独立可配置为输入或者输出的 SPDIF、I2S 音频信号。支持 4 个独立的字库定 制型 OSD;可处理隔行和逐行视频或者图形输入信号;有四路独…...
Spring之注解
SpringIOC注解 组件添加标记注解: Component:该注解标记类表示该类为一个普通类,表示为IOC中的一个组件bean Repository:该注解用于将数据访问层(Dao层)的类标识为Spring中的Bean Service&…...
【UniApp开发小程序】悬浮按钮+出售闲置商品+商品分类选择【基于若依管理系统开发】
文章目录 界面效果界面实现悬浮按钮实现商品分类选择界面使元素均匀分布 闲置商品描述信息填写界面价格校验 界面效果 【悬浮按钮】 【闲置商品描述信息填写界面】 【商品分类选择界面】 【分类选择完成】 界面实现 悬浮按钮实现 悬浮按钮漂浮于页面之上,等页面…...
一百三十三、Hive——Hive外部表加载含有JSON格式字段的CSV文件数据
一、目标 在Hive的ODS层建外部表,然后加载HDFS中的CSV文件数据 注意:CSV文件中含有未解析的JSON格式的字段数据,并且JSON字段中还有逗号 二、第一次建外部表,直接以,分隔行字段,结果JSON数据只显示一部分…...
rust gtk 桌面应用 demo
《精通Rust》里介绍了 GTK框架的开发,这篇博客记录并扩展一下。rust 可以用于桌面应用开发,我还挺惊讶的,大学的时候也有学习过 VC,对桌面编程一直都很感兴趣,而且一直有一种妄念,总觉得自己能开发一款很好…...
《嵌入式 - 工具》J-link读写MCU内部Flash
1 J-Link简介 J-Link是SEGGER公司为支持仿真ARM内核芯片推出的JTAG仿真器。配合IAR EWAR,ADS,KEIL,WINARM,RealView等集成开发环境支持所有ARM7/ARM9/ARM11,Cortex M0/M1/M3/M4, Cortex A5/A8/A9等内核芯片的仿真,是学…...
算法练习-LeetCode1071. Greatest Common Divisor of Strings
题目地址:LeetCode - The Worlds Leading Online Programming Learning Platform Description: For two strings s and t, we say "t divides s" if and only if s t ... t (i.e., t is concatenated with itself one or more times). Given two strin…...
Nuget不小心用sudo下载后怎么在user里使用
问题发生 协同开发的过程中,同时在dotnet里面添加了nuget的grpc包,在不清楚的情况下执行自动生成脚本,下载nuget包失败,说是权限不足,于是就使用了sudo进行自动生成,结果在下一次重新打包的过程中ÿ…...
软件测试技能大赛环境搭建及系统部署报告
环境搭建及系统部署报告 环境搭建与配置过程(附图) JDK环境变量配置截图 【截取JDK环境变量配置截图】 查看JDK版本信息截图 【截取使用命令查看JDK版本信息截图,必须截取查看信息成功截图】 root账号成功登录MySQL截图 【截取使用root账…...
浅谈现代通信技术
目录 1.传统通信方法 2.传统通信方式的缺点 3.现代通信技术 4.现代通信技术给人类带来的福利 1.传统通信方法 传统通信方法指的是在数字化通信之前使用的传统的通信方式。以下是一些常见的传统通信方法: 1. 书信:通过邮件或快递等方式发送纸质信件。这…...
windows环境下adb 下载和配置,连接手机。
ADB下载地址: https://adbdownload.com/ 选择下载windows系统的。 下载后解压,查看adb.exe所在的目录,如下 这里将路径复制下来:D:\ADB 配置到系统环境变量中。 然后再打开cmd,输入adb version查看版本。 出现…...
[STL]list使用介绍
[STL]list使用 注:本文测试环境是visual studio2019。 文章目录 [STL]list使用1. list介绍2. 构造函数3. 迭代器相关函数begin函数和end函数rbegin函数和rend函数 4. 容量相关函数empty函数size函数 5. 数据修改函数push_back函数和pop_back函数push_front函数和pop…...
k8s服务发现之第五弹--使用 Service 连接到应用
Kubernetes 的网络模型 通过前面教程的学习,我们已经可以将容器化的应用程序在 Kubernetes 中运行起来,并且发布到 Kubernetes 内/外的网络上。 通常,Docker 使用一种 host-private 的联网方式,在此情况下,只有两个容…...
SAP ABAP 自定义表数据导入
一:效果展示: 读取 Excel 数据到 SAP 数据库表。 二:源码: *&---------------------------------------------------------------------* *& Report ZTEST_DRW02 *&----------------------------------------------------------…...
目标检测识别——大恒(DaHeng)相机操作与控制编程
文章目录 引言正文相关开发库的介绍编程准备配置引用头文件GalaxyIncludes.h配置lib文件 具体编程过程初始化和反初始化枚举设备开关设备 属性控制属性控制器种类 图像采集控制和图像处理采单帧回调采集 总结 引言 在做老师的横向项目时,需要用大恒相机,…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...
