nodejs实现一个用户只能点一次赞功能
在开发社交应用或内容平台时,我们常常需要实现用户对某个内容(如、图片等)只能点赞一次的功能。提供几种解决方案,并通过代码示例详细展示如何实现这一功能。
解决方案
为了确保用户只能对某个内容点赞一次,我们需要记录用户的点赞行为。通常可以通过以下方式实现:
1. 使用数据库存储用户的点赞状态。
2. 利用缓存技术(如Redis)来快速判断用户是否已点赞。
3. 结合JWT(JSON Web Token)或其他会话管理机制,确保每个用户的性。
接下来,我们将从不同的角度和思路来实现这一功能。
思路一:使用关系型数据库
我们可以使用关系型数据库(如MySQL、PostgreSQL)来存储用户的点赞记录。以下是具体实现步骤:
数据库设计
假设我们有一个 likes
表,结构如下:
- id
: 自增主键
- user_id
: 用户ID
- content_id
: 内容ID(如ID)
- created_at
: 点赞时间
实现代码
javascript
const express = require('express');
const mysql = require('mysql');
const app = express();
app.use(express.json());</p>
<p>// 创建MySQL连接池
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'password',
database: 'my_database'
});</p>
<p>// 点赞接口
app.post('/like/:contentId', (req, res) => {
const userId = req.body.userId; // 假设从前端传递用户ID
const contentId = req.params.contentId;</p>
<p>// 查询用户是否已经点赞
pool.query('SELECT * FROM likes WHERE user<em>id = ? AND content</em>id = ?', [userId, contentId], (err, results) => {
if (err) {
return res.status(500).send('Database error');
}</p>
<pre><code>if (results.length > 0) {
// 如果用户已点赞,则返回错误信息
return res.status(400).send('You have already liked this content');
} else {
// 否则插入新的点赞记录
pool.query('INSERT INTO likes (user_id, content_id, created_at) VALUES (?, ?, NOW())', [userId, contentId], (err, result) => {
if (err) {
return res.status(500).send('Database error');
}
res.status(200).send('Like successful');
});
}
});
});
// 启动服务器
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
思路二:使用Redis缓存
如果需要更高效的性能,可以使用Redis来存储用户的点赞状态。Redis的键值对存储非常适合这种场景。
实现代码
javascript const express = require('express'); const redis = require('redis'); const app = express(); app.use(express.json());</p> <p>// 创建Redis客户端 const client = redis.createClient({ host: 'localhost', port: 6379 });</p> <p>client.on('error', (err) => { console.error('Redis error:', err); });</p> <p>// 点赞接口 app.post('/like/:contentId', (req, res) => { const userId = req.body.userId; // 假设从前端传递用户ID const contentId = req.params.contentId; const likeKey = <code>like:${userId}:${contentId}
;// 检查用户是否已经点赞 client.get(likeKey, (err, reply) => { if (err) { return res.status(500).send('Redis error'); }
if (reply) { // 如果用户已点赞,则返回错误信息 return res.status(400).send('You have already liked this content'); } else { // 否则设置点赞状态 client.setex(likeKey, 86400, 'true', (err) => { // 设置过期时间为1天 if (err) { return res.status(500).send('Redis error'); } res.status(200).send('Like successful'); }); }
});
});// 启动服务器
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
思路三:结合JWT与后端验证
如果我们的应用使用了JWT进行身份验证,可以在JWT中嵌入用户的标识,并在后端验证用户是否已点赞。
实现代码
javascript const express = require('express'); const jwt = require('jsonwebtoken'); const mysql = require('mysql'); const app = express(); app.use(express.json());</p> <p>// 创建MySQL连接池 const pool = mysql.createPool({ host: 'localhost', user: 'root', password: 'password', database: 'my_database' });</p> <p>// JWT密钥 const secretKey = 'your<em>secret</em>key';</p> <p>// 验证JWT中间件 function authenticateToken(req, res, next) { const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; if (token == null) return res.sendStatus(401);</p> <p>jwt.verify(token, secretKey, (err, user) => { if (err) return res.sendStatus(403); req.user = user; next(); }); }</p> <p>// 点赞接口 app.post('/like/:contentId', authenticateToken, (req, res) => { const userId = req.user.id; // 从JWT中获取用户ID const contentId = req.params.contentId;</p> <p>// 查询用户是否已经点赞 pool.query('SELECT * FROM likes WHERE user<em>id = ? AND content</em>id = ?', [userId, contentId], (err, results) => { if (err) { return res.status(500).send('Database error'); }</p> <pre><code>if (results.length > 0) { // 如果用户已点赞,则返回错误信息 return res.status(400).send('You have already liked this content'); } else { // 否则插入新的点赞记录 pool.query('INSERT INTO likes (user_id, content_id, created_at) VALUES (?, ?, NOW())', [userId, contentId], (err, result) => { if (err) { return res.status(500).send('Database error'); } res.status(200).send('Like successful'); }); }
});
});// 登录接口(生成JWT)
app.post('/login', (req, res) => {
const user = { id: req.body.userId }; // 假设用户登录成功后返回用户ID
const accessToken = jwt.sign(user, secretKey, { expiresIn: '1h' });
res.json({ accessToken });
});// 启动服务器
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
以上三种思路分别使用了关系型数据库、Redis缓存以及JWT结合后端验证的方式实现了用户只能点赞一次的功能。每种方法都有其适用场景:
- 关系型数据库适合数据持久化需求较高的场景。
- Redis缓存适合对性能要求较高且数据不需要长期保存的场景。
- JWT结合后端验证适合已有身份验证机制的应用。根据实际需求选择合适的方案即可!