Sequelize查询结果嵌套数据结构转换问题求助
解决Sequelize查询结果转结构时字段丢失的问题
你遇到的问题其实是Sequelize返回的是Model实例对象,而非普通JavaScript对象导致的。模拟数据能正常工作是因为它本身就是纯JS对象,但Sequelize的实例是经过封装的,直接解构可能无法正确获取到所有字段(尤其是别名字段或关联模型的属性)。
解决方案:先将Sequelize实例转为普通对象
Sequelize提供了get({ plain: true })方法,可以把Model实例转换成扁平化的普通JS对象,之后再进行数据结构转换就和你模拟的场景一致了。
修改你的第一次尝试代码如下:
const query = await product.findOne({ where: { product_id: id }, include: { model: category, attributes: ['category_id', ['name', 'category_name']], include: { model: department, attributes: ['department_id', ['name', 'department_name']] } }, attributes: [] }); // 将Sequelize实例转换为普通JS对象 const plainQuery = query.get({ plain: true }); const data = plainQuery.categories.map( ({ category_id, category_name, department }) => ({ category_id, category_name, department_id: department.department_id, department_name: department.department_name }) ); ctx.body = data;
为什么之前的代码会丢失字段?
Sequelize的Model实例把实际数据存储在dataValues属性中,虽然你可以通过instance.category_name直接访问属性,但在解构赋值时,可能因为实例的getter逻辑、属性代理等原因,无法正确提取到所有字段(尤其是你设置的别名字段category_name、department_name)。转换成普通对象后,所有属性都变成了常规的键值对,解构和map操作就和处理普通JS对象完全一致了。
另一种替代方法:查询时使用raw: true
如果你想在查询阶段直接获取纯JS对象,可以在查询选项中添加raw: true,但需要注意的是,嵌套关联的结构会有所变化(关联模型的字段会带上前缀),所以这种方式需要你调整后续的处理逻辑:
const query = await product.findOne({ where: { product_id: id }, include: { model: category, attributes: ['category_id', ['name', 'category_name']], include: { model: department, attributes: ['department_id', ['name', 'department_name']] } }, attributes: [], raw: true // 直接返回纯JS对象 }); // 注意:raw模式下关联的department字段会保持嵌套结构 const data = query.categories.map( ({ category_id, category_name, department }) => ({ category_id, category_name, department_id: department.department_id, department_name: department.department_name }) ); ctx.body = data;
不过更推荐第一种get({ plain: true })的方式,它能保留Sequelize查询的嵌套结构,同时转换成普通对象,更符合你的需求。
内容的提问来源于stack exchange,提问作者Yangwook Ian Jeong
相关产品推荐
相关产品推荐

