一个用Nodejs写的网站如何实现淘宝评分这种制度(express+mongoose)

一个用Nodejs写的网站如何实现淘宝评分这种制度(express+mongoose)

用express简单的假设了一个购物网站,在评分这个需求的时候卡壳了,具体如下

每个用户都可以对某个商品进行评分,但只能评一次,商品会显示平均分,就像京东,淘宝那种

自己想了下是可以做,但是实现太过繁琐。google又不知道如何搜起

求思路,谢谢~

9 回复

要实现一个类似淘宝的评分系统,我们可以使用Node.js、Express框架和Mongoose库来构建后端逻辑。以下是一个简化的实现思路和示例代码,帮助你理解如何实现这个功能。

数据模型设计

首先,我们需要定义两个主要的数据模型:UserProductUser 模型用来存储用户信息,而 Product 模型则包含商品信息以及评分相关的字段。

User Model (user.js)

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
    username: { type: String, required: true, unique: true },
    password: { type: String, required: true }
});

module.exports = mongoose.model('User', userSchema);

Product Model (product.js)

const mongoose = require('mongoose');

const productSchema = new mongoose.Schema({
    name: { type: String, required: true },
    description: { type: String },
    rating: { type: Number, default: 0 },
    numRatings: { type: Number, default: 0 },
    ratings: [{ userId: mongoose.Schema.Types.ObjectId, score: { type: Number, min: 1, max: 5 } }]
});

module.exports = mongoose.model('Product', productSchema);

后端逻辑实现

接下来,我们创建一些API来处理用户的评分操作。这里我们将创建一个POST路由来接收用户的评分,并更新商品的评分信息。

Route (routes/product.js)

const express = require('express');
const router = express.Router();
const Product = require('../models/product');

router.post('/rate/:productId', async (req, res) => {
    const { productId } = req.params;
    const { userId, score } = req.body;

    try {
        // 查找产品
        let product = await Product.findById(productId);

        if (!product) {
            return res.status(404).send('Product not found.');
        }

        // 检查用户是否已经评分
        const existingRating = product.ratings.find(rating => rating.userId.toString() === userId);
        
        if (existingRating) {
            return res.status(400).send('You have already rated this product.');
        }

        // 添加新的评分
        product.ratings.push({ userId, score });
        product.numRatings += 1;
        product.rating = ((product.rating * (product.numRatings - 1)) + score) / product.numRatings;

        // 保存更改
        await product.save();

        res.send('Rating added successfully.');
    } catch (error) {
        res.status(500).send(error.message);
    }
});

module.exports = router;

总结

上述代码中,我们定义了两个数据模型:UserProduct。然后,我们通过一个POST请求来处理用户对商品的评分。我们检查用户是否已经对该商品进行了评分,如果尚未评分,则将新评分添加到产品文档中,并计算新的平均评分。

希望这能帮助你理解和实现一个简单的评分系统!如果你有任何进一步的问题或需要更详细的实现,请告诉我。


哇,是乃啊~
=3=
这个实现用非关系数据库不太好做呢

想了一下,可以再用户里添加个已评分的商品list

{
    _id: xx,
    username: 'xxx',
    ...,
    rated_list: [
        {商品id: 5},
        {商品id2: 4},
    ],
    ...
}

不过这样查询的时候可能麻烦点了,但是可控比较好,判断某商品是否评过分比较简单(嘛,也不算简单)。
以至于算平均分,在商品那里加个average,每次评分的时候改变,目测并发大的话要加锁。

和我想的差不多,我试着实现下,谢啦~ PS:最近到处见到你

先去到list,然后把它push到list里然后在update。
细节就不清楚了(其实也就这样啦w

去到/取到

最笨的办法就是建一个评分的collection呗,就三个字段[ "userId", "goodsId", "score" ]

然后在商品的collection里面加两个字段:平均分和评分人数。

然后用户评分的时候先去看看该用户有没有评这个商品,如果有的话就加上去,然后把商品里面的平均分乘以人数然后加上当前用户评分除以人数加一,然后人数也加一存回数据库。

这个恐怕只能按关系型数据库的老套路更加方便了

为了实现类似淘宝或京东的评分系统,我们可以使用Node.js、Express和Mongoose来构建。我们将创建两个主要模型:UserProduct。每个用户可以对一个商品进行一次评分,而商品则会显示平均分。

数据库设计

  1. User 模型

    • 用户ID (userId)
    • 用户名 (username)
  2. Product 模型

    • 商品ID (productId)
    • 商品名称 (productName)
    • 评分 (ratings) - 数组类型,每个元素包含用户ID和评分
    • 平均评分 (averageRating) - 计算得出的平均评分

示例代码

1. 安装依赖

npm install express mongoose body-parser

2. 配置 Mongoose 模型

const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/shopdb', { useNewUrlParser: true, useUnifiedTopology: true });

const UserSchema = new mongoose.Schema({
    userId: String,
    username: String
});

const ProductSchema = new mongoose.Schema({
    productId: String,
    productName: String,
    ratings: [
        {
            userId: { type: String, ref: 'User' },
            rating: { type: Number, min: 1, max: 5 }
        }
    ],
    averageRating: { type: Number, default: 0 }
});

const User = mongoose.model('User', UserSchema);
const Product = mongoose.model('Product', ProductSchema);

3. API 路由处理

const express = require('express');
const bodyParser = require('body-parser');

const app = express();
app.use(bodyParser.json());

// 创建用户
app.post('/users', async (req, res) => {
    const user = new User(req.body);
    await user.save();
    res.status(201).send(user);
});

// 添加评分
app.post('/products/:productId/rate', async (req, res) => {
    const { userId, rating } = req.body;
    const product = await Product.findOne({ productId: req.params.productId });
    if (!product) return res.status(404).send('Product not found');

    // 检查用户是否已经评分
    const existingRating = product.ratings.find(r => r.userId === userId);
    if (existingRating) return res.status(409).send('You have already rated this product');

    // 添加新的评分
    product.ratings.push({ userId, rating });
    product.averageRating = calculateAverage(product.ratings);

    await product.save();
    res.send(product);
});

// 计算平均评分
function calculateAverage(ratings) {
    if (ratings.length === 0) return 0;
    const total = ratings.reduce((sum, rating) => sum + rating.rating, 0);
    return (total / ratings.length).toFixed(2);
}

app.listen(3000, () => console.log('Server running on port 3000'));

解释

  • UserProduct 模型定义了所需的数据结构。
  • 在添加评分时,首先检查用户是否已对该商品评分。
  • 使用 calculateAverage 函数计算当前评分的平均值,并更新到商品模型中。
  • 这样,每次新增评分后,商品的平均评分会自动更新。

通过这种方式,我们可以在Node.js项目中轻松实现一个简单的评分系统。

回到顶部