9-1 个人资料需求分析
- 不同类型(如字符串、数组)等属性
- 字段过滤
9-2 个人资料的 schema 设计
- 分析个人资料的数据结构
- 设计个人资料的 schema
models/users.js
const mongoose = require('mongoose')
const { Schema, model } = mongoose
const userSchema = new Schema({
__v: {type: Number, select: false},
name: { type: String, required: true },
password: {type: String, required: true, select: false},
avatar_url: { type: String}, // 头像地址
gender: { type: String, enum: ['male','female'], default: 'male', required: true}, // 性别,可枚举
headline: { type: String}, // 一句话介绍
locations: { type: [{type: String}]}, //住址:字符串数组
business: { type: String},
employments: {
type: [{
company: { type: String},
job: { type: String}
}]
}, // 职业经历
educations: {
type: [{
school: { type: String},
major: { type: String},
diploma: { type: Number, enum: [1, 2,,3, 4, 5]}, // 学历
entrance_year: { type: Number}, // 入学年份
graduaction_year: { type: Number} // 毕业年份
}]
}
})
module.exports = model('User',userSchema)
9-3 个人资料的参数校验
- 分析个人资料的数据结构
- 编写代码校验个人资料参数
controllers/users.js
async update (ctx) {
ctx.verifyParams({
name: {type: 'string', required: false},
password: { type: 'string', required: false},
avatar_url: { type: 'string', required: false},
gender: { type: 'string', required: false},
headline: { type: 'string', required: false},
locations: { type: 'array', itemType: 'string', required: false}, //数组类型,数组每一项为字符串
business: { type: 'string', required: false},
employments: { type: 'array', itemType: 'object', required: false}, //数组类型,数组每一项为对象
educations: { type: 'array', itemType: 'object', required: false} //数组类型,数组每一项为对象
})
const user = await User.findByIdAndUpdate(ctx.params.id, ctx.request.body)
if (!user) {
ctx.throw(404, '用户不存在')
}
ctx.body = user
}
9-4 RESTful API 最佳实践——字段过滤
字段过滤
即在请求某个特定对象接口的时候,比如特定用户接口的时候,可以通过查询字符串上的一些字段选择性地显示用户有哪些字段显示,哪些不显示。
- 重新设计 schema 默认隐藏部分字段
- 通过查询字符串显示隐藏字段
controllers/users.js
const mongoose = require('mongoose')
const { Schema, model } = mongoose
const userSchema = new Schema({
__v: {type: Number, select: false},
name: { type: String, required: true },
password: {type: String, required: true, select: false},
avatar_url: { type: String}, // 头像地址
gender: { type: String, enum: ['male','female'], default: 'male', required: true}, // 性别,可枚举
headline: { type: String}, // 一句话介绍
locations: { type: [{type: String}], select: false}, //住址:字符串数组
business: { type: String, select: false},
employments: {
type: [{
company: { type: String},
job: { type: String}
}],
select: false
}, // 职业经历
educations: {
type: [{
school: { type: String},
major: { type: String},
diploma: { type: Number, enum: [1, 2,,3, 4, 5]}, // 学历
entrance_year: { type: Number}, // 入学年份
graduaction_year: { type: Number} // 毕业年份
}],
select: false
}
})
module.exports = model('User',userSchema)
- 默认locations、employments、business、educations不显示。
- 在原基础上加入 select: false即可。
如果我们想要显示location等字段,可以通过拼接url地方式,如:
http://localhost:3000/users/5fc613c14a1cc80a341353ce?fields=locations;business
controllers/users.js
async findById (ctx) {
const { fields } = ctx.query
console.log(fields) // locations;business
const selectFields = fields.split(';').filter(f => f).map(f => ' +' + f).join('')
console.log(selectFields) // +locations +business
const user = await User.findById(ctx.params.id).select(selectFields)
if (!user) {
ctx.throw(404, '用户不存在')
}
ctx.body = user
}