Mongoose按用户ID查询书籍:默认全量返回、按需触发bookStatus过滤
核心问题定位
- 现有
BookList类的filter方法存在语法层级错误:类方法内部嵌套了同名的filter(req)函数,代码闭合逻辑混乱,根本无法正常执行 - 原有过滤逻辑硬编码了
bookStatus: 'in stock'的固定条件,没有做入参存在性判断,导致无论用户是否主动传递过滤参数,都会强制筛除非库存状态的书籍 - 传参逻辑不匹配:控制器中调用
.filter(req)传入了req对象,但类构造函数没有预留req的存储位置,代码无法正常读取req里的路由参数
改造实现逻辑
- 类构造函数新增req实例的存储能力,确保可以正常读取路由中的用户ID(保留用户书籍的权限隔离逻辑,这部分属于权限校验,不能放开)
- 重写
filter方法的判断规则:- 基础过滤条件固定保留当前用户的书籍归属校验
- 仅当请求的查询参数中存在
bookStatus字段时,才把该条件追加到查询规则中,移除硬编码的默认库存过滤
- 修正类方法的语法结构,理顺嵌套逻辑
改造后的完整可运行代码
BookList 类修正
class BookList { constructor(query, queryString, req) { this.query = query; this.queryString = queryString; // 存储req实例,统一读取路由、查询参数 this.req = req; } filter() { // 基础权限过滤:仅返回当前请求用户所属的书籍 const baseFilter = { userid: this.req.params.userid }; // 仅当用户主动传入bookStatus查询参数时,才追加对应过滤逻辑 if (this.req.query.bookStatus) { baseFilter.bookStatus = this.req.query.bookStatus; } this.query = this.query.find(baseFilter); return this; } sort() { if (this.queryString.sort) { const sortBy = this.queryString.sort.split(',').join(' '); this.query = this.query.sort(sortBy); } else { this.query = this.query.sort('-createdAt'); } return this; } paginate() { const page = Number(this.queryString.page) || 1; const limit = Number(this.queryString.limit) || 100; const skip = (page - 1) * limit; this.query = this.query.skip(skip).limit(limit); return this; } } module.exports = BookList;
控制器修正
exports.getBooks = async (req, res, next) => { // 实例化类时传入req对象,匹配构造函数的参数定义 const bookList = new BookList(Book.find(), req.query, req) .filter() .sort() .paginate(); const books = await bookList.query; res.status(200).json({ books }); };
运行效果
- 无额外查询参数请求接口时:返回当前用户的全部书籍,不会硬卡库存状态限制
- 请求中携带
?bookStatus=xxx格式参数时:自动应用对应状态的过滤规则,返回匹配状态的书籍 - 全程保留用户书籍的权限隔离,不会出现越权查看他人书籍的问题
内容的提问来源于stack exchange,提问作者boomchickawawa
相关产品推荐
相关产品推荐

