中继项目中的更新突变问题

Posted

技术标签:

【中文标题】中继项目中的更新突变问题【英文标题】:Problem with update mutation in Relay project 【发布时间】:2020-03-14 10:35:02 【问题描述】:

我正在处理 Relay 项目,更新突变存在问题。我是 Relay 的新手,我很难确定问题与什么有关 - 通过承诺或 Relay 设置。 发送突变时,findOneAndUpdate 函数不会保存从 args 接收到的数据。我使用 console.log(args) 检查数据是否进入 updateHero 函数。 我将提供我的项目文件。如果有任何帮助,我将不胜感激!感谢关注。

hero.js:

const mongoose = require('mongoose');
mongoose.set('useFindAndModify', false);

const Schema = mongoose.Schema;

const heroSchema = new Schema(
  name: 
    type: String,
    required: true
  ,
  description: 
    type: String,
    required: true
  ,
  img: 
    type: String,
    required: true
  ,
  date: 
    type: Date,
    required: true
  
);

var heroModel = mongoose.model("Hero", heroSchema);

module.exports = 
  getHeroes: () => 
    return heroModel.find().sort( _id: -1 )
      .then(heroes => 
        return heroes.map(hero => 
          return 
            ...hero._doc,
            id: hero.id,
            date: new Date(hero.date).toISOString()
          ;
        );
      )
      .catch(err => 
        throw err;
      );
  ,
  getHero: id => 
    return heroModel.findOne( _id: id );
  ,
  createHero: hero => 
    return heroModel(hero).save();
  ,
  removeHero: id => 
    return heroModel.findByIdAndRemove(id);
  ,
  updateHero: (args) => 
    return new Promise((resolve) => 
      (async () => 
        await heroModel.findOneAndUpdate(
           id: args.id ,
          
            name: args.name,
            description: args.description,
            img: args.img,
            date: args.date
          ,
           new: true 
        );
      )();
      resolve("OK");
    );
  
;

mutation.js:

const 
  GraphQLObjectType,
  GraphQLNonNull,
  GraphQLString,
  GraphQLBoolean
 = require('graphql');

const  fromGlobalId, mutationWithClientMutationId  = require('graphql-relay');
const  Hero  = require('./types/hero');

const heroModel = require('./models/hero');

const CreateHeroMutation = mutationWithClientMutationId(
  name: "CreateHero",
  inputFields: 
    name:  type: new GraphQLNonNull(GraphQLString) ,
    description:  type: new GraphQLNonNull(GraphQLString) ,
    img:  type: new GraphQLNonNull(GraphQLString) ,
    date:  type: new GraphQLNonNull(GraphQLString) 
  ,
  outputFields: 
    hero: 
      type: Hero
    
  ,
  mutateAndGetPayload: args => 
    return new Promise((resolve, reject) => 
      heroModel.createHero(
        name: args.name,
        description: args.description,
        img: args.img,
        date: new Date(args.date)
      )
        .then(hero => resolve( hero ))
        .catch(reject);
    );
  
);

const UpdateHeroMutation = mutationWithClientMutationId(
  name: "UpdateHero",
  inputFields: 
    id:  type: new GraphQLNonNull(GraphQLString) ,
    name:  type: new GraphQLNonNull(GraphQLString) ,
    description:  type: new GraphQLNonNull(GraphQLString) ,
    img:  type: new GraphQLNonNull(GraphQLString) ,
    date:  type: new GraphQLNonNull(GraphQLString) 
  ,
  outputFields: 
    hero: 
      type: Hero
    
  ,
  mutateAndGetPayload: async args => 
    return new Promise((resolve, reject) => 
      heroModel.updateHero(args)
        .then(hero => resolve( hero ))
        .catch(reject);
    );
  
);

const RemoveHeroMutation = mutationWithClientMutationId(
  name: "RemoveHero",
  inputFields: 
    id:  type: new GraphQLNonNull(GraphQLString) ,
  ,
  outputFields: 
    deleted:  type: GraphQLBoolean ,
    deletedId:  type: GraphQLString 
  ,
  mutateAndGetPayload: async ( id ,  viewer ) => 
    const  id: productId  = fromGlobalId(id);
    const result = await heroModel.removeHero(productId);
    return  deletedId: id, deleted: true ;
  
);

const Mutation = new GraphQLObjectType(
  name: "Mutation",
  description: "kjhkjhkjhkjh",
  fields: 
    createHero: CreateHeroMutation,
    removeHero: RemoveHeroMutation,
    updateHero: UpdateHeroMutation
  
);

module.exports = Mutation;

可能需要这些文件。节点.js:

const  nodeDefinitions, fromGlobalId  = require('graphql-relay');
const heroModel = require('./models/hero');

const  nodeInterface, nodeField  = nodeDefinitions(
  (globalId) => 
    const  type, id  = fromGlobalId(globalId);
    if (type == "Hero") 
      return heroModel.getHero(id);
     else 
      return null;
    
  ,
  (obj) => 
    const  Hero  = require('./types/hero');
    if (obj instanceof Hero) 
      return Hero;
    
    return null;
  
);

module.exports =  nodeInterface, nodeField ;

hero.js(类型):

const 
  GraphQLObjectType,
  GraphQLString
 = require('graphql');

const  globalIdField, connectionDefinitions  = require('graphql-relay');
const  nodeInterface  = require('../nodes');

const Hero = new GraphQLObjectType(
  name: "Hero",
  description: "lkjlkjlkjlkjlk",
  interfaces: [nodeInterface],
  fields: () => (
    id: globalIdField(),
    name: 
      type: GraphQLString,
      description: "The name of the hero"
    ,
    description: 
      type: GraphQLString,
      description: "Hero biography"
    ,
    img: 
      type: GraphQLString,
      description: "Portrait of hero"
    ,
    date: 
      type: GraphQLString,
      description: "Date of birth"
    
  )
);

const  connectionType: HeroConnection  = connectionDefinitions(
  nodeType: Hero
);

module.exports =  Hero, HeroConnection ;

【问题讨论】:

【参考方案1】:

中继服务器需要 fromGlobalID 方法将 id 作为参数传递给 mongoose 模式。解决方案是传递“全局 id”和输入参数:

const UpdateHeroMutation = mutationWithClientMutationId(
  name: "UpdateHero",
  inputFields: 
    id:  type: new GraphQLNonNull(GraphQLString) ,
    name:  type: new GraphQLNonNull(GraphQLString) ,
    description:  type: new GraphQLNonNull(GraphQLString) ,
    img:  type: new GraphQLNonNull(GraphQLString) ,
    date:  type: new GraphQLNonNull(GraphQLString) 
  ,
  outputFields: 
    updated:  type: GraphQLBoolean ,
    updatedId:  type: GraphQLString 
  ,
  mutateAndGetPayload: async (args) => 
    const  id: productId  = fromGlobalId(args.id);
    const result = await heroModel.updateHero(productId, args);
    return  updatedId: args.id, updated: true ;
  
);

模式中的updateHero函数:

updateHero: (id, args) => 
    return heroModel.findByIdAndUpdate(
      id,
      
        name: args.name,
        description: args.description,
        img: args.img,
        date: args.date
      ,
       new: true 
    );
  

原来如此。

【讨论】:

以上是关于中继项目中的更新突变问题的主要内容,如果未能解决你的问题,请参考以下文章

使用后续突变和缺失片段中继 commitUpdate 回调

进行后续突变后中继不更新

中继突变中没有字段“clientMutationId”

中继突变不能动态工作

中继突变:突变分页关联

应该如何对列表中的项目进行重新排序,并更新多个对象,如何使用 GraphQL 突变进行持久化?