如何在React游轮网站中使用Knex Joins关联船舶与评论数据
问题解答
1. 初始关联建立方式错误
你当前在ships表中加review_id关联reviews的逻辑完全不符合业务场景:一艘邮轮对应多条评论,属于典型的一对多关联,外键应该存在「多」的那一侧,也就是在reviews表中保留ship_id字段关联ships表的主键id,这样才能实现一艘船绑定多条评论的需求。反过来在ships表存review_id的话,一艘船最多只能绑定一条评论,完全不满足后续用户新增评论的要求。
2. 现有查询代码存在的问题
- 函数
getReviews没有定义入参,where条件里用到的id属于未定义变量,运行直接报错 - 函数内部重复声明
db变量,会覆盖外部初始化的数据库连接,且你用到的testConn没有提前定义 - 第一个then仅打印日志没有返回查询到的record,第二个then里用到的
dbrecord属于未定义变量,最终拿不到返回结果 - 如果要查询单条船的所有评论,需要删除
.first()方法,这个方法只会返回匹配到的第一条数据
3. 前后端交互逻辑说明
必须要编写API层代码,完整交互流程如下:
- 前端点击船舶跳转评论页时,携带当前船舶的id作为参数请求后端接口
- 后端API层接收船舶id参数,调用数据库层的关联查询方法,拿到数据后返回给前端
- 前端拿到评论数据后渲染到页面
- 用户提交新评论时,前端把船舶id+用户填写的评论内容一起传给后端新增接口,后端往reviews表插入数据后返回成功状态,前端刷新评论列表即可
修正后的参考代码
数据库层代码
const environment = process.env.NODE_ENV || 'development' const config = require('../../knexfile')[environment] const db = require('knex')(config) // 根据船舶id查询关联评论 function getReviewsByShipId(shipId) { console.log('server/db/dbreviews.js getReviewsByShipId called!') return db('ships') .join('reviews','ships.id', '=', 'reviews.ship_id') .where('reviews.ship_id', '=', shipId) // 仅需要第一条评论保留.first(),查所有评论删除该行即可 .first() .select("*", "ships.id AS sid", "reviews.id AS rid") .then(record => { console.log('查询到的评论数据:', record) return record }) } // 新增评论方法 function addReview(reviewData) { return db('reviews').insert(reviewData).returning('*') } module.exports = { getReviewsByShipId, addReview }
API层示例代码(Express为例)
const express = require('express') const router = express.Router() const reviewDb = require('./dbreviews') // 获取指定船舶的评论接口 router.get('/reviews/:shipId', async (req, res) => { try { const reviews = await reviewDb.getReviewsByShipId(req.params.shipId) res.json(reviews) } catch (err) { res.status(500).json({error: '获取评论失败'}) } }) // 新增评论接口 router.post('/reviews', async (req, res) => { try { const newReview = await reviewDb.addReview(req.body) res.json(newReview) } catch (err) { res.status(500).json({error: '新增评论失败'}) } }) module.exports = router
内容的提问来源于stack exchange,提问作者Rob Wilkinson
相关产品推荐
相关产品推荐

