序列化和响应请求GraphQL

时间:2019-03-29 20:44:57

标签: node.js graphql sequelize.js

我尝试对我的请求GraphQL进行回复。

我尝试了很多事情,但目前我始终具有Sequence响应,而没有Buckets响应(属于To关联)。

我有2张桌子:

  

序列[id | is_active]

     

桶[id | fk_language_id | fk_sequence_id | is_active]

model / sequence.js

'use strict';
module.exports = (sequelize, DataTypes) => {
    // define sequence
    const Sequence = sequelize.define('sequence', {
        is_active: {type: DataTypes.BOOLEAN}
    });

    Sequence.associate = function (models) {

    models.Sequence.hasMany(models.Bucket, {
        foreignKey: 'fk_sequence_id'
    });

    return Sequence;
};

model / bucket.js

'use strict';
module.exports = (sequelize, DataTypes) => {
    const Bucket = sequelize.define('bucket', {
        code     : {type: DataTypes.STRING},
        is_active: {type: DataTypes.BOOLEAN}
    });

    Bucket.associate = function (models) {
        models.Bucket.belongsTo(models.Language, {
            foreignKey: 'fk_language_id',
        });    

        models.Bucket.belongsTo(models.Sequence, {
            foreignKey: 'fk_sequence_id',
        });
    };

    return Bucket;
};

schema.js

  # Sequence
  type Sequence {
    id: Int!,
    code: String,
    buckets: [Bucket],
    is_active: Boolean
  }

  # Bucket
  type Bucket {
    id: Int!,
    code: String
    blocks: [Block]
    is_active: Boolean
  }

  # SequenceInput
  input SequenceInput {
    buckets: [BucketInput],
    is_active: Boolean
  }

  # BucketInput
  input BucketInput {
    code: String,
    fk_language_id: Int,
    fk_sequence_id: Int,
    is_active: Boolean
  }

  type Query {
    sequences: [Sequence]
    sequence(id: Int): Sequence

    buckets: [Bucket]
    bucket(id: Int): Bucket
  }

  type Mutation {
    createSequence(input: SequenceInput): Sequence,
  } 

请求GraphQL

mutation {
  createSequence(input: { 
    is_active: false, 
    buckets: [
      {fk_language_id: 2, code: "Test"}
    ] 
  }) {
    is_active,
    buckets {
      id,
      code
    }
  }
}

但是我得到了这个结果,存储桶未加载:

{
  "data": {
    "createSequence": {
      "is_active": false,
      "buckets": []
    }
  }
}

我的突变:

...
Sequence      : {
    buckets(sequence) {
        return models.Bucket.findAll({
            where: {id: sequence.id}
        });
    },
    ...
},
...
Mutation    : {
createSequence(_, {input}) {
    let sequenceId = 0;

    // Create Sequence
    return models.Sequence.create(input)
                 .then((sequence) => {
                     sequenceId = sequence.id;
                     console.log('sequence created');
                     // Create Bucket
                     // Foreach on buckets

                     return Promise.map(input.buckets, function (bucket) {
                         bucket.fk_sequence_id = sequenceId;
                         console.log('bucket created');
                         return models.Bucket.create(bucket);
                     })

                 })
                 .then(() => {
                     console.log('load created', sequenceId);
                     return models.Sequence.findOne({
                         where  : {id: sequenceId},
                         include: [
                             {
                                 model: models.Bucket,
                                 where: { fk_sequence_id: sequenceId }
                             }
                         ]
                     }).then((response) => {
                         console.log(response);

                         return response;
                     })

                 });

},
}

最终的console.log显示许多信息...

sequence {
  dataValues: 
   { id: 416,
     is_active: false,
     created_at: 2019-03-29T20:33:56.196Z,
     updated_at: 2019-03-29T20:33:56.196Z,
     buckets: [ [Object] ] },
  _previousDataValues: 
   { id: 416,
     is_active: false,
     created_at: 2019-03-29T20:33:56.196Z,
     updated_at: 2019-03-29T20:33:56.196Z,
     buckets: [ [Object] ] },
  _changed: {},
  _modelOptions: 
   { timestamps: true,
     validate: {},
     freezeTableName: true,
     underscored: false,
     paranoid: false,
     rejectOnEmpty: false,
     whereCollection: { id: 416 },
     schema: null,
     schemaDelimiter: '',
     defaultScope: {},
     scopes: {},
     indexes: [],
     name: { plural: 'sequences', singular: 'sequence' },
     omitNull: false,
     createdAt: 'created_at',
     updatedAt: 'updated_at',
     sequelize: 
      Sequelize {
        options: [Object],
        config: [Object],
        dialect: [Object],
        queryInterface: [Object],
        models: [Object],
        modelManager: [Object],
        connectionManager: [Object],
        importCache: [Object],
        test: [Object] },
     hooks: {} },
  _options: 
   { isNewRecord: false,
     _schema: null,
     _schemaDelimiter: '',
     include: [ [Object] ],
     includeNames: [ 'buckets' ],
     includeMap: { buckets: [Object] },
     includeValidated: true,
     attributes: [ 'id', 'is_active', 'created_at', 'updated_at' ],
     raw: true },
  isNewRecord: false,
  buckets: 
   [ bucket {
       dataValues: [Object],
       _previousDataValues: [Object],
       _changed: {},
       _modelOptions: [Object],
       _options: [Object],
       isNewRecord: false } ] }

1 个答案:

答案 0 :(得分:1)

您的突变解析器返回一个Promise,该Promise解析为Model实例。有问题的诺言将在以下行中返回:

return models.Sequence.create(input)

这样,服务器将等待该承诺得到解决,然后再传递值。其他行动也正在等待该诺言,但它们不是诺言的返回,因此不会等待。

您要做的就是等待所有操作完成,然后再兑现您的诺言。

createSequence: async (parent, { input }) => {
  const sequence = await models.Sequence.create({
    is_active: input.is_active
  })
  if (!input.buckets) return sequence
  // You may have to modify your Sequence.buckets resolver to avoid fetching buckets again.
  sequence.buckets = await Promise.all(input.buckets.map(bucket => {
    // You can avoid these if checks by implementing stricter input types.
    // e.g. buckets: [BucketInput!]!
    if (!bucket) return null
    return models.Bucket.create({
      ...bucket,
      fk_sequence_id: sequence.id
    })
  }))
  return sequence
}

此外,请确保您的Sequence.buckets解析器不会用错误的数据覆盖存储桶。您提供的解析器将尝试将存储桶主键与序列主键匹配,而不是将正确的外键与主键匹配。

这是一个可以使用的解析器:

buckets: (parent) => (
  parent.buckets // This line may conflict with some of your code and cause problems.
  || models.Bucket.findAll({
    where: {fk_sequence_id: parent.id}
  })
)