如何基于关联Schema计算平均值?按书籍ID/标题求书评平均评分
从关联Schema计算书籍平均评分的解决方案
我明白你需要基于书籍的ID或标题,计算它关联的书评的平均评分。从你给出的Book Schema来看,bookReviews字段是引用BookReview文档的ObjectId数组,对吧?那我们可以通过两种常见方式来实现这个需求:使用Mongoose的聚合管道或者结合populate后计算,下面分别详细说明。
方法一:使用MongoDB聚合管道(推荐,性能更优)
聚合管道直接在数据库层面计算,避免把所有书评数据拉到应用层处理,适合数据量较大的场景。我们可以通过$lookup关联BookReview集合,然后计算平均值。
按书籍ID查询并计算平均评分
const Book = mongoose.model('Book', bookSchema); async function getAverageRatingByBookId(bookId) { const result = await Book.aggregate([ // 匹配目标书籍 { $match: { _id: mongoose.Types.ObjectId(bookId) } }, // 关联BookReview集合,获取该书籍的所有书评 { $lookup: { from: 'bookreviews', // 注意这里是BookReview模型对应的集合名,通常是小写复数 localField: 'bookReviews', foreignField: '_id', as: 'reviews' } }, // 计算平均评分,如果没有书评则返回0 { $project: { _id: 1, title: 1, averageRating: { $avg: '$reviews.rating' // 假设BookReview Schema里有rating字段 } } } ]); return result.length > 0 ? result[0] : null; }
按书籍标题查询并计算平均评分
只需要修改$match阶段的条件:
async function getAverageRatingByBookTitle(title) { const result = await Book.aggregate([ { $match: { title: { $regex: title, $options: 'i' } } }, // 模糊匹配,忽略大小写 { $lookup: { from: 'bookreviews', localField: 'bookReviews', foreignField: '_id', as: 'reviews' } }, { $project: { _id: 1, title: 1, averageRating: { $avg: '$reviews.rating' } } } ]); return result; // 返回所有匹配标题的书籍及其平均评分 }
方法二:使用Mongoose Populate后在应用层计算
如果你的数据量不大,也可以先populate出所有关联的书评,然后在代码里计算平均值:
async function getAverageRatingByBookId(bookId) { const book = await Book.findById(bookId).populate('bookReviews'); if (!book) return null; // 计算平均评分 const reviews = book.bookReviews; if (reviews.length === 0) { return { ...book.toObject(), averageRating: 0 }; } const totalRating = reviews.reduce((sum, review) => sum + review.rating, 0); const averageRating = totalRating / reviews.length; return { ...book.toObject(), averageRating }; }
注意事项
- 确保
BookReviewSchema里确实有rating字段(数值类型),如果字段名不同,记得修改代码里的对应部分。 - 聚合管道中的集合名
bookreviews要和你的BookReview模型对应的MongoDB集合名一致,Mongoose默认会把模型名转为小写复数。 - 如果需要处理大量数据,优先选择聚合管道的方式,性能会比populate后计算好很多。
内容的提问来源于stack exchange,提问作者HKIT9
相关产品推荐
相关产品推荐

