【问题标题】:Sequelize and response request GraphQLSequelize 和响应请求 GraphQL
【发布时间】:2019-08-20 20:34:09
【问题描述】:

我尝试对我的请求 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 } ] }

【问题讨论】:

    标签: node.js graphql sequelize.js


    【解决方案1】:

    您的变异解析器返回一个 Promise,该 Promise 解析为一个模型实例。有问题的承诺在这一行返回:

    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}
      })
    )
    

    【讨论】:

    • 感谢您的回答@JemiSalo!我已经实现了你的代码,但我得到了相同的结果,我的数组中总是没有存储桶。我更新了我的帖子(突变)并删除了 import BlueBird。
    • 我未能查看您的 Sequence.buckets 解析器。你有一个导致问题的主要错误。我将更新我的答案以包含解决方案。
    • 在解析器中,我添加了一个“return parent.buckets || ...”你能确认一下吗?因为只有您在解析器中的代码(parent.buckets ||...)返回 null。非常感谢你的帮助 !!!你拯救了一天!
    • 分解我写的解析器:parent.buckets 将被返回,如果它是真实的。当createSequence 的分辨率返回父级时就是这种情况。但通常, parent.buckets 是 nullundefined 并且将返回 Bucket.findAll 承诺。我通过复制粘贴您的代码进行了尝试,它似乎有效。第一个值parent.buckets 只是为了获得更好的性能。如果它引起问题,你可以放弃它。
    猜你喜欢
    • 2021-10-22
    • 2018-09-07
    • 2017-02-22
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    • 2019-07-19
    • 2020-01-28
    • 2020-04-11
    相关资源
    最近更新 更多