百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Mongoose - 在 NodeJs 中优雅地建立 MongoDb 对象模型

toyiye 2024-06-21 12:15 11 浏览 0 评论

在 NodeJs 中写 MongoDb 的校验,构造和业务逻辑简直是一种拖累。这就是为什么我们写了 Mongoose。

什么是 MongoDb 和 Mongoose

MongoDb

MongoDB is an open-source document database that provides high performance, high availability, and automatic scaling.

MongoDb 是一个开源的文档数据库,可提供高性能,高可用性和自动缩放。

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。

MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

Mongoose

Mongoose provides a straight-forward, schema-based solution to model your application data. It includes built-in type casting, validation, query building, business logic hooks and more, out of the box.

Mongoose 为你的应用程序数据提供了一个直接的,基于模型的解决方案。他包括内置的类型转换,校验,建立查询,业务逻辑的钩子等。

Mongoose是一个提供了MongoDB地相映射的Node.js库,它在Node.js中与ORM(Object Relational Mapping)有着类似的接口。如果你不熟悉ORM或者Mongoose中的Object Data Mapping(ODM),意思是Mongoose将数据库中的数据转换为JavaScript对象以供你在应用中使用。

为什么使用 Mongoose

Let’s face it, writing MongoDB validation, casting and business logic boilerplate is a drag

安装和使用 Mongoose

  1. 安装
  2. $ npm install mongoose --save-dev
  3. 使用
  4. $ touch index.js
  5. 在 index.js 文件中引入 Mongoose ,并连接数据库
var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/myblog');//连接上 myblog 数据库

开始使用 Mongoose 操作 MongoDb

注:本文默认已经搭好 Nodejs 和 MongoDb 环境,若未搭建环境,请移步至 -> 还在编写当中

假设我们在构建一个博客,需要将博文存储至数据库中。

而每一篇博文的结构如下:

{
 title: '标题',
 author: '作者',
 date: '时间',
 comments: '评论',
 tags: '标签',
 body: '正文'
}

OK, Go!

Mongoose 中的 Schema 和 Model

在使用 Mongoose 前,先了解一下 Mongoose 中的 Schema 和 Model。

  • Schema
  • 在使用 Mongoose 前,先了解一下 Mongoose 中的 Schema 和 Model。

Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

在 Mongoose 中,所有东西都从一个 Schema 开始。每一个 schema 都映射到一个 MongoDb 的集合,并定义了该集合中的文档的形式。

  • 定义一个 Schema:
var Schema = mongoose.Schema;
var userSchema = new Schema({
 name: String,
 pass: String,
 email: String,
 createTime: Date,
 lastLogin: Date
});
  • Schema 中的每一个键都定义了一个文档的一个属性。在上面的例子中,我们定义了用户名 name ,它会被映射为 String 的 Schema 类
  • 型,注册时间 createTime 会被映射为 Date 的 Schema 类型。
  • 允许的 Schema 类型有:(了解更多)
  • String
  • Number
  • Date
  • Buffer
  • Boolean
  • Mixed
  • ObjectId
  • Array
  • 用法:
  • 自定义方法
  • 模型的实例都是一个个的文档,文档中自带许多方法。同时,我们也可以定义我们自己的方法。
var userSchema = new Schema({
 name: String,
 pass: String,
 email: String,
 createTime: Date,
 lastLogin: Date,
 type: String
});
//根据该用户的类型区查找该类型下的所有用户
userSchema.methods.findUsersByType = function(name, cb){
 return this.find({type: this.type}, cb);
}
//新建模型
var User = mongoose.model('User', userSchema);
//使用
var newUser = new User({...});
newUser.findUsersByType(function(err, users){
 err && return console.error(err);
 console.log(users);
})
  • 这样就向 User 的实例添加了一个自定义的方法。
  • 静态方法
  • 同样的,向模型中添加自定义方法也是很简单。
userSchema.statics.findUsersByName = function(name, cb){
 return this.find({name: new RegExp(name, "ig")}, cb);
}
//使用
User.findUsersByName('leung', function(err, users){
 err && return console.error(err);
 console.log(users);
})
  • 查询辅助
  • 可以自定义一个查询的辅助函数,它和实体的方法类似,但是供 Mongoose 查询使用。
userSchema.query.byName = function(name){
 return this.find({name: new RegExp(name, "ig")});
}
//使用
userSchema.find().byName('leung').exec(function(err, users){
 err && return console.error(err);
 console.log(users);
})
  • 索引
  • MongoDb 支持第二个索引,在使用 Mongoose 的时候,可以在定义 Schema 的时候定义索引。
//定义方法1
var userSchema = new Schema({
 name: String,
 pass: String,
 email: String,
 createTime: {type: Date, index: true},
 lastLogin: {type: Date, index: true},
 type: String
});
//定义方法2
userSchema.index({ createTime: 1, lastLogin: -1 });
  • Mongoose 会在程序启动的时候,对于每个定义了索引的字段自动调用 ensureIndex 函数。当在不需要这些索引的时候,可以使用下列 4 种方式关闭索引。
mongoose.connect('mongodb://user:pass@localhost:port/database', { config: { autoIndex: false } });
// or
mongoose.createConnection('mongodb://user:pass@localhost:port/database', { config: { autoIndex: false } });
// or
userSchema.set('autoIndex', false);
// or
new Schema({..}, { autoIndex: false });
  • 虚拟字段
  • 虚拟字段可以让你很方便的在文档中存取,但是不会写入数据库中。getter 方法在格式化或者合并字段的时候很有用,而 setter 方法则在反格式化或者时将多个值合并的时候有用。
var personSchema = new Schema({
 name:{
 firstName: String,
 lastName: String
 }
});
var Person = mongoose.model('Person', personSchema);
//定义虚拟字段 fullName
personSchema.virtual('name.fullName').get(function(){
 console.log(this);
 return this.name.firstName + ' ' + this.name.lastName;
})
var me = new Person({name: {firstName: 'zhong', lastName: 'Lueng'}});
console.log(me);
console.log(me.name.fullName) //zhong Lueng
  • 虚拟字段的 setter 方法会在其他校验前使用,因此,即使字段时必须的,虚拟字段也会正常执行。
  • 只用非虚拟字段才可以在查询或者字段选择中使用。
  • 配置项
  • Schema 有许多可配置的配置项,可以在新建 Schema 时或者直接设置。
new Schema({..}, options);
//or
var schema = new Schema({..});
schema.set(option, value);
  • 有效的配置项:
  • autoIndex
  • capped
  • collection
  • emitIndexErrors
  • id
  • _id
  • minimize
  • read
  • safe
  • shardKey
  • strict
  • toJSON
  • toObject
  • typeKey
  • validateBeforeSave
  • versionKey
  • skipVersioning
  • timestamps
  • Model
  • 在 Mongoose 中,模型是通过已定义的 Schema 生成,这些模型的实例可以保存并检索数据库中的文档。数据库中的所有文档都是通过模型来创建和检索。
  • 创建文档
  • 文档是模型的实例,创建文档和将其保存到数据库中是非常简单的:
var animalSchema = new Schema({
 type: String
});
var Animal = mongoose.model('Animal', animalSchema);
var cat = new Animal({type: 'cat'});
cat.save((err, doc) =>{
 err && console.error(err);
 console.log('doc is saved');//saved
});
// or
Animal.create({type: 'cat'}, (err, doc) =>{
 err && console.error(err);
 //saved!
})
  • 查询文档
  • 在 Mongoose 中查询文档是很方便的,同时支持 MongoDb 原生语法,模型中有许多内置的静态函数: find , where , findById , findOne 等等, 也支持链式调用。
Animal.find({type: 'dog'}).where('age').gt(2).limit(10).exec();
  • 移除文档
  • 每个模型都有一个默认的移除方法,可以移除所有符合搜索条件的文档。
Animal.remove({type: 'dongbeihu'}, (err, res){
 err && console.error(err);
 //removed!
})
  • 更新文档
  • 每个模型都有他自己的更新方法,供更新数据库中所有符合条件的文档,同时不返回任何东西。
  • 如果需要更新单个文档,并且返回更新后的文档,请使用 findOneAndUpdate

下面可开始使用 Mongoose 来操作 MongoDb 数据库了。

  1. 创建博文的 Schema
var Schema = mongoose.Schema;
var blogSchema = new Schema({
 title: String, //标题
 author: String, //作者
 body: String, //正文
 comments: [{ //评论
 author: String,
 date: Date,
 body: String
 }],
 date: {type: Date, default: Date.now}, //发布时间
 isDelete: Boolean, //是否删除
 tags: [{type: String}] //标签
}, {collection: 'blog'}); //选择 blog 集合
  1. 创建一个 Blog 模型
  2. 创建了一个模型之后,我们就可以通过模型去创建新的文档或者去操作数据库。
var Blog = mongoose.model('Blog', blogSchema);
  1. 创建一个新的实体对象
  2. 这里的所有数据都是通过 Mockjs 进行模拟。详情移步至 Mockjs 官网
  3. 使用 mockjs 模拟真实数据
var Mock = require('mockjs');
var Random = Mock.Random;
exports.getBlog = function(){
 var blog = {
 title: Random.ctitle(3,10), //随机生成一个长度3-10之间的中文标题
 author: Random.cword(2,3), //随机生成一个长度2-3之间的中文单词
 body: Random.cparagraph(1,3), //随机生成1-3段中文段落
 comments: [],
 date: Random.datetime('yyyy-MM-dd HH:mm'), //随机生成一个时间点
 tags: []
 }
 var length =~~(Math.random()*10) +5;
 for (var i = 0; i < length; i++) {
 blog.comments.push(Mock.mock({
 author: Random.cword(2,3), //随机生成一条评论的作者名字
 body: Random.cparagraph(1,3), //随机生成一条评论的内容
 date: Random.datetime('yyyy-MM-dd HH:mm') //随机生成评论的时间点
 }))
 }
 var length2 =~~(Math.random()*4) +2;
 for (var i = 0; i < length2; i++) { //随机加入几个标签
 var tag = Random.pick(['nodejs','js','html','css','java','php','python']);
 if(blog.tags.indexOf(tag) == -1) blog.tags.push(tag)
 }
 return blog;
}
  1. 生成一个 blog 实体对象
var newBlog = require('./blog'); //导入随机生成数据的模块
var blogObj = newBlog.getBlog();
var blog = new Blog(blogObj) //将随机生成的数据转换成为 blog 模型的实体。
//生成实体对象的另一种方法.
//此方法相当于创建了一个实体并写入数据库,再返回一个 promise 对象。
//var blog2 = Blog.create(blogObj);
  1. 数据库的 CRUD
  • create
  • 基于实体对象: Entity.save(callback);
  • Example:
var blogObj = newBlog.getBlog();
var blog = new Blog(blogObj)
blog.save((err, doc) => {
 if(err) return console.error(err);
 console.log(doc);
})
//{title: '...', author: '...'}

结果:

  • 基于模型: Model.create(Obj, callback)
  • Example:
Blog.create(blogObj, (err, doc) => {
 if(err) return console.error(err);
 console.log(doc);
})
//{title: '...', author: '...'}

结果:

  • delete
  • 基于实体对象:Entity.remove(cb)
  • 基于模型:Model.remove(query, cb)
  • update
  • 基于实体对象:Entity.update(cb)
  • Example:
var blog = new Blog(blogObj);
blog.save((err, doc) => { //先添加新的博文
 if(err) console.error(err);
 console.log('Entity.save()');
 console.log(doc);
 //通过实体直接更新博文
 blog.update({$set: {date: new Date(), title: 'Update From Mongoose'}}, (err2, doc) => {
 if(err2) return console.error(err2);
 console.log(doc);
 })
})

结果:

  • 更新后在 Mongobooster 中的数据
  • 基于模型:
Model.update(query, docs, options, cb)

参数:

  • query:查询条件。
  • docs:需要更新的数据。
  • options:配置项。
  • cb:回调。
  • 返回:
  • <Qeury> this
  • 其中,配置项中有效的配置如下:
  • safe (boolean) safe mode (defaults to value set in schema (true))
  • upsert (boolean) whether to create the doc if it doesn’t match (false)
  • multi (boolean) whether multiple documents should be updated (false)
  • runValidators: if true, runs update validators on this command. Update validators validate the update operation against the model’s schema.
  • setDefaultsOnInsert: if this and upsert are true, mongoose will apply the defaults specified in the model’s schema if a new document is created. This option only works on MongoDB * >= 2.4 because it relies on MongoDB’s $setOnInsert operator.
  • strict (boolean) overrides the strict option for this update
  • overwrite (boolean) disables update-only mode, allowing you to overwrite the doc (false)
  • context (string) if set to ‘query’ and runValidators is on, this will refer to the query in custom validator functions that update * validation runs. Does nothing if runValidators is false.
  • 只有传入 callback 时,所有的更新操作才会被执行
  • Example:
//以下操作均不会执行
var q = Blog.where({title: /del/g}).update({$set: {comments: []}});
//等同于
//var q = where({title: /del/g}).update({comments: []});
//下面三条命令均会执行更新操作。
//q.exec()
//q.update(true)
var q = Blog.where({title: /del/g}).update({$set: {comments: []}}, (err) => {
 //executes
});
//将文档重写为空文档
var q = Blog.where({ _id: id }).setOptions({ overwrite: true })
q.update({ }, callback); // executes
//or
//var q = Blog.update({_id: id}, {}, {overwrite: true}, callback);
//将所有博文的创建日期设置为今天
Blog.where()
 .setOptions({ multi: true })
 .update({ $set: { date: new Date() }}, callback)
//or
//Blog.update({}, { $set: { date: new Date() }}, { multi: true }, callback);
  • 批量更新结果:
  • read(query)
  • find 操作包含了许多查询的操作,在这里只介绍最常用的几种查询方法,具体的可以查阅官网的 API Guide
  • $where (注意前面的 $)
  • 可以传入一个 javascript 函数或者表达式作为查询条件。
  • 用法:$where(js)
//在数据库中找出作者名字长度为 2 且评论大于 10 条的博文:
Blog
.$where('this.comments.length >= 10 && this.author.length === 3')
//.$where(function(){return this.comments.length >= 10 && this.author.length === 3;})
.select('title author commentSize')
.find((err, docs)=>{
 if(err) return console.error(err);
 console.log(docs);
})

查询结果:

  • where
  • 指定一个查询字段,供后续的链式调用.字段可以是字符串,也可以时一个完整的查询对象。
  • 用法:where(path, val),path 可以是字符串或是对象
//查找评论数大于8条,且标题含有叫字的博文
Blog
.where('commentSize').gte(8)
//.where({'commentSize':{gte: 8}})
.where('title', /叫/g)
.select('title author commentSize')
.find((err, docs)=>{
 if(err) return console.error(err);
 console.log(docs);
})

查询结果:

  • all
  • 指定一个 all 的查询条件。all 的使用方法可以查阅 MongoDb 官方文档
  • 用法: all([path], val),当只传递一个参数时,查询字段已经在 where 中指定。
//查询出同时含有 html 和 js 标签的博文
Blog
// .where('tags').all(['html', 'js'])
.find().all('tags', ['html', 'js'])
.select('title author tags')
.find((err, docs)=>{
 if(err) return console.error(err);
 console.log(docs);
})

查询结果:

  • and
  • 指定一个 and 的查询条件。
  • 用法:and(array)
//查找出标题带有叫字,且含有 js 标签的博文
Blog.find()
.and([{title: /叫/g}, {tags: 'js'}])
.select('title author tags')
.find((err, docs)=>{
 if(err) return console.error(err);
 console.log(docs);
})

查询结果:

  • count
  • 返回符合指定条件的文档个数。
  • 用法:count(query, callback)
//查找出标题带有叫字,且含有 js 标签的博文
Blog.find()
.and([{title: /叫/g}, {tags: 'js'}])
.select('title author tags')
.count((err, docs)=>{
 if(err) return console.error(err);
 console.log(docs);
})

查询结果:

  • limit
  • 指定返回查询条数。
  • 用法:limit(Number)。
  • or / nor
  • 指定一组查询条件,只要符合/不符合其中一个条件即可。
  • 用法:or(array) / nor(array)
//查询所有标签包含 js, 或者标题有“叫”字的博文
Blog.find()
.or([{title: /叫/g}, {tags: 'css'}])
.select('title author tags')
.find((err, docs)=>{
 if(err) return console.error(err);
 console.log(docs);
})

查询结果:

//查询所有标签不包含 js或者标题不含有“叫”字的博文
Blog.find()
.nor([{title: /叫/g}, {tags: 'js'}])
.select('title author tags')
.find((err, docs)=>{
 if(err) return console.error(err);
 console.log(docs);
})

查询结果:

  • slice
  • 返回符合指定条件的文档个数。
  • 用法:slice([path], value)
//查出所有的博文,并显示每个博文的第一个标签。
Blog
.where('tags').slice(1)
.select('title')
.limit(4)
.exec((err, doc) => {
 console.log(doc);
})

查询结果

  • sort
  • 设定排序规则。
  • 用法:sort(arg).参数可以是对象,可以是字符串。
//查出所有的博文,并按照标题排序。
Blog.find()
.sort('title')
//.sort({title: 1}) //传入对象参数
//.sort({title: -1}) //传入对象参数,标题倒叙
//.sort('-title') //传入对象字符串,标题倒叙
.limit(4)
.exec((err, doc) => {
 console.log(doc);
})
  • 查询结果:
  1. validate
  2. Mongoose 中,在定义 Schema 的时候,允许用户自定义字段的校验规则。当在 Schema 中定义校验规则的时候,需要遵守下列规则:
  • 校验规则需要在 Schema 中定义。
  • 校验会在 save 操作前调用。
  • 可以通过 doc.validate(callback) 和 doc.validateSync() 手动校验。
  • 未定义校验规则的字段将不会校验,除非是 required 必要字段。
  • 校验时异步递归的,当使用 Model.save 时,子文档的校验规则将会立即调用,有错误时,执行的 Model.save 会接收到错误。
  • 校验时自定义的。
  • 普通的校验定义:
var personSchema = new Schema({
name:{
 type: String,
 validate:{
 validator: function(value){
 //只能以字母开头,只能包含英文数字下划线。
 return /^[a-zA-Z][a-zA-Z0-9_]*$/.test(value);
 },
 message: '{VALUE} is not a valid username. It must begin with a letter.'
 },
 required: [true, 'Username is required']
},
phone: {
 type: String,
 validate: {
 validator: function(v) {
 //11位电话号码
 return /\d{11}/.test(v);
 },
 message: '{VALUE} is not a valid phone number!'
 },
 required: [true, 'User phone number required']
},
gender:{
 type: String,
 enum: {
 //只能是男女
 values: ['female', 'male'],
 message: '{VALUE} is not a valid gender'
 },s
}
},{collection: 'person'})
var Person = mongoose.model('Person', personSchema);
//测试数据
var one = new Person({
 name: '123',
 phone:'11111',
 gender:' male'
})
  • 我们使用 one.validateSync() 对数据进行验证,其验证结果如下:
  • Mongoose 中内置的验证如下:
  • 所有的 Schema 都有 required 校验规则,必要校验器会调用 Schema 的 chenckRequired() 函数去校验该字段的值是否符合规则。
  • Number 类型有 min 和 max。
  • String 类型有 enum, minlength, maxlength, match的校验器。
  • required:必填校验。
  • 可以传入的参数为:boolean[,String]。当只传 true 或者 false 时,用于定义该字段是否为必填;当传入第二个参数 String 时,该信息作为校验失败的错误提示语。
  • enum:枚举类型校验。
  • 接受参数类型为:Array/ Object。当类型为 Array 时,指定该字段的值必须在该数组中;当传入类型为 Object 时,可以定义两个键值队:values 和 message,values的类型为 Array,指定字段的值必须在数组 values 中,message 指定校验失败的错误提示语。
  • validator:校验的对象。
  • 该对象包含 2 个键值队:
  • validate 可以是正则表达式,也可以是一个函数。
  • message 则是错误信息提示语。
  • min ,max:对数字类型的进行大小校验。第二个参数可以为字符串,作为错误提示语。
  • minlength ,maxlength:对字符串类型的进行长度校验。第二个参数可以为字符串,作为错误提示语。
  • match:接受一个正则表达式进行验证。第二个参数可以为字符串,作为错误提示语。
  • trim:字符串在校验时,是否去除前后字符串。默认为 false。

使用 Mongoose 的自动校验功能,可以省下许多校验操作。

以前,我们直接使用 Mongodb 去操作数据,每次读取操作都要打开,关闭数据库,但是当网页刷新/访问过于频繁时,就会出现数据库来不及关闭,又开始新的查询,就可能会出现 error。

现在,我们使用 Mongoose,打开数据库的连接之后,db 就会一直处于连接状态,不需要在访问时才打开连接,操作完后关闭连接,Error 也不再出现了。而且,代码的易读性也提高了不少。

希望本文能帮助到您!

点赞+转发,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓-_-)

关注 {我},享受文章首发体验!

每周重点攻克一个前端技术难点。更多精彩前端内容私信 我 回复“教程”

相关推荐

如何用 coco 数据集训练 Detectron2 模型?

随着最新的Pythorc1.3版本的发布,下一代完全重写了它以前的目标检测框架,新的目标检测框架被称为Detectron2。本教程将通过使用自定义coco数据集训练实例分割模型,帮助你开始使...

CICD联动阿里云容器服务Kubernetes实践之Bamboo篇

本文档以构建一个Java软件项目并部署到阿里云容器服务的Kubernetes集群为例说明如何使用Bamboo在阿里云Kubernetes服务上运行RemoteAgents并在agents上...

Open3D-ML点云语义分割实验【RandLA-Net】

作为点云Open3D-ML实验的一部分,我撰写了文章解释如何使用Tensorflow和PyTorch支持安装此库。为了测试安装,我解释了如何运行一个简单的Python脚本来可视化名为...

清理系统不用第三方工具(系统自带清理软件效果好不?)

清理优化系统一定要借助于优化工具吗?其实,手动优化系统也没有那么神秘,掌握了方法和技巧,系统清理也是一件简单和随心的事。一方面要为每一个可能产生累赘的文件找到清理的方法,另一方面要寻找能够提高工作效率...

【信创】联想开先终端开机不显示grub界面的修改方法

原文链接:【信创】联想开先终端开机不显示grub界面的修改方法...

如意玲珑成熟度再提升,三大发行版支持教程来啦!

前期,我们已分别发布如意玲珑在deepinV23与UOSV20、openEuler24.03发行版的操作指南,本文,我们将为大家详细介绍Ubuntu24.04、Debian12、op...

118种常见的多媒体文件格式(英文简写)

MP4[?mpi?f??]-MPEG-4Part14(MPEG-4第14部分)AVI[e?vi??a?]-AudioVideoInterleave(音视频交错)MOV[m...

密码丢了急上火?码住7种console密码紧急恢复方式!

身为攻城狮的你,...

CSGO丨CS2的cfg指令代码分享(csgo自己的cfg在哪里?config文件位置在哪?)

?...

使用open SSL生成局域网IP地址证书

某些特殊情况下,用户内网访问多可文档管理系统时需要启用SSL传输加密功能,但只有IP,没有域名和证书。这种情况下多可提供了一种免费可行的方式,通过openSSL生成免费证书。此方法生成证书浏览器会提示...

Python中加载配置文件(python怎么加载程序包)

我们在做开发的时候经常要使用配置文件,那么配置文件的加载就需要我们提前考虑,再不使用任何框架的情况下,我们通常会有两种解决办法:完整加载将所有配置信息一次性写入单一配置文件.部分加载将常用配置信息写...

python开发项目,不得不了解的.cfg配置文件

安装软件时,经常会见到后缀为.cfg、.ini的文件,一般我们不用管,只要不删就行。因为这些是程序安装、运行时需要用到的配置文件。但对开发者来说,这种文件是怎么回事就必须搞清了。本文从.cfg文件的创...

瑞芯微RK3568鸿蒙开发板OpenHarmony系统修改cfg文件权限方法

本文适用OpenHarmony开源鸿蒙系统,本次使用的是开源鸿蒙主板,搭载瑞芯微RK3568芯片。深圳触觉智能专注研发生产OpenHarmony开源鸿蒙硬件,包括核心板、开发板、嵌入式主板,工控整机等...

Python9:图像风格迁移-使用阿里的接口

先不多说,直接上结果图。#!/usr/bin/envpython#coding=utf-8importosfromaliyunsdkcore.clientimportAcsClient...

Python带你打造个性化的图片文字识别

我们的目标:从CSV文件读取用户的文件信息,并将文件名称修改为姓名格式的中文名称,进行规范资料整理,从而实现快速对多个文件进行重命名。最终效果:将原来无规律的文件名重命名为以姓名为名称的文件。技术点:...

取消回复欢迎 发表评论:

请填写验证码