【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文件 具体编程过程初始化和反初始化枚举设备开关设备 属性控制属性控制器种类 图像采集控制和图像处理采单帧回调采集 总结 引言 在做老师的横向项目时,需要用大恒相机,…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...

【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...
加密通信 + 行为分析:运营商行业安全防御体系重构
在数字经济蓬勃发展的时代,运营商作为信息通信网络的核心枢纽,承载着海量用户数据与关键业务传输,其安全防御体系的可靠性直接关乎国家安全、社会稳定与企业发展。随着网络攻击手段的不断升级,传统安全防护体系逐渐暴露出局限性&a…...
Monorepo架构: Nx Cloud 扩展能力与缓存加速
借助 Nx Cloud 实现项目协同与加速构建 1 ) 缓存工作原理分析 在了解了本地缓存和远程缓存之后,我们来探究缓存是如何工作的。以计算文件的哈希串为例,若后续运行任务时文件哈希串未变,系统会直接使用对应的输出和制品文件。 2 …...

何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践,很多人以为AI已经强大到不需要程序员了,其实不是,AI更加需要程序员,普通人…...

Win系统权限提升篇UAC绕过DLL劫持未引号路径可控服务全检项目
应用场景: 1、常规某个机器被钓鱼后门攻击后,我们需要做更高权限操作或权限维持等。 2、内网域中某个机器被钓鱼后门攻击后,我们需要对后续内网域做安全测试。 #Win10&11-BypassUAC自动提权-MSF&UACME 为了远程执行目标的exe或者b…...