Sequelize关联加载PostgreSQL数组字段数据时出现500错误求助
问题
使用Sequelize搭配原生支持数组的PostgreSQL数据库,尝试通过主键加载单个Artifact数据,同时加载所有关联的Artist数据(要求该Artist的artifactID数组中包含当前Artifact的ID)。单独加载Artist数据能返回正确结果,但关联加载时出现500错误,找不到Sequelize中处理PostgreSQL数组的相关资料,请求帮助。
API代码:
const router = require('express').Router(); const Sequelize = require('sequelize'); const Op = Sequelize.Op; const { Artist, Post, Artifact } = require('../db'); //GET /api/ all artifacts router.get('/', async(req, res, next) => { try { const artifactList = await Artifact.findAll(); res.send(artifactList) } catch (e) { next(e); } }); router.get('/:id', async(req, res, next) => { try { const artifact = await Artifact.findByPk(req.params.id); const artists = await Artist.findAll({ where: { artifactID: { [Op.in]: parseInt(req.params.id) } } }); res.send({artifact, artists}); } catch (e) { next(e); } }) module.exports = router;
报错信息:
GET https://octopus-house.herokuapp.com/api/artifacts/1 500 (Internal Server Error)
解决方案
你用Op.in来匹配PostgreSQL数组字段是错误的——Op.in是用来判断字段值是否在给定数组里,而你要的是检查数组字段里是否包含某个值,得用Op.contains或者PostgreSQL原生数组操作符。
修改后的接口代码:
router.get('/:id', async(req, res, next) => { try { const artifactId = parseInt(req.params.id); const artifact = await Artifact.findByPk(artifactId); const artists = await Artist.findAll({ where: { artifactID: { [Op.contains]: [artifactId] // 用数组包裹目标值,匹配数组字段是否包含该值 } } }); res.send({artifact, artists}); } catch (e) { console.error(e); // 加上错误日志,方便排查具体报错原因 next(e); } })
补充说明:
Op.contains对应PostgreSQL的@>操作符,传入数组参数即可检查目标数组字段是否包含该数组内的所有元素(这里只传一个值,就是检查是否包含该值)- 提前把ID转成数字存起来,避免重复解析,代码更简洁
- 加上
console.error(e)能在服务器端看到具体错误详情,方便后续排查其他问题
也可以用PostgreSQL原生语法实现,效果一致:
where: { [Op.and]: Sequelize.literal(`"artifactID" @> ARRAY[${artifactId}]::integer[]`) }
内容的提问来源于stack exchange,提问作者blowecle
相关产品推荐
相关产品推荐

