如何将hasMany关联对象数组转为id数组,解决Ember读取Hasura关联数据问题
你遇到的问题是Ember Data默认不识别Hasura返回的嵌套对象数组格式的关联字段,优先选择在Ember侧通过序列化器适配,不需要修改Hasura侧的返回结构,避免破坏接口的通用性。
问题原因
Ember Data默认遵循JSON:API规范,关联数据默认要求放在relationships字段下,或显式配置嵌入式关联规则。你当前将photos对象数组直接放在movie的属性层级,Ember Data没有对应配置的话不会将其识别为hasMany关联,自然无法读取渲染。
方案1:Ember侧实现(推荐)
步骤1:定义正确的模型关联
首先保证movie和photo模型的关联声明正确:app/models/movie.js
import Model, { attr, hasMany } from '@ember-data/model'; export default class MovieModel extends Model { @attr('string') movieid; @attr('string') description; // 因为数据是和movie一起返回的,async设为false不需要单独发起请求 @hasMany('photo', { async: false }) photos; }
app/models/photo.js
import Model, { belongsTo } from '@ember-data/model'; export default class PhotoModel extends Model { @belongsTo('movie') movie; }
步骤2:配置序列化器适配嵌套结构
新增movie对应的序列化器,识别嵌入式的photos字段:app/serializers/movie.js
import JSONSerializer from '@ember-data/serializer/json'; export default class MovieSerializer extends JSONSerializer { // 配置嵌入式关联规则,设为ids表示只提取关联资源的id,需要完整属性则设为'records' embeddedRecords = { photos: 'ids' }; // 如果你需要直接把photos转成纯id数组存储,也可以重写normalize方法手动处理 normalize(modelClass, resourceHash) { if (Array.isArray(resourceHash.photos)) { resourceHash.photos = resourceHash.photos.map(item => item.id); } return super.normalize(...arguments); } }
如果你使用的是JSONAPISerializer,只需要调整normalize方法,把嵌套的photos数据移动到relationships字段下即可。
方案2:Hasura侧实现(不推荐)
如果非要在后端修改返回格式,你可以通过PostgreSQL自定义函数或Hasura聚合查询实现,示例查询写法如下:
query GetMovies { movies { id movieid description photo_ids: photos_aggregate { nodes { id } } } }
但该方案会修改接口返回结构,其他端如果需要使用photos的其他属性时无法直接获取,因此不建议使用。
内容的提问来源于stack exchange,提问作者ELsssss
相关产品推荐
相关产品推荐

