web-dev-qa-db-fra.com

Comment faire une requête de mutation pour insérer une liste de champs (tableau) dans GraphQL

récemment j'ai commencé à travailler sur GraphQL, je suis capable d'insérer des données dans un schéma plat sans aucun problème mais quand il s'agit d'un tableau de données, je reçois une erreur comme

 { "errors": [ {  "message": "Must be input type" } ]}

Je teste ma requête à l'aide de postman, ma requête de mutation est

mutation M { 

AddEvent
  (

    title: "Birthday event"   

    description:"Welcome to all" 

    media:[{url:"www.google.com", mediaType:"image" }]

    location:[{address:{state:"***", city:"****"}}]

   ) 

{title,description,media,location,created,_id}}

Voici mon schéma d'événement:

EventType = new GraphQLObjectType({
  name: 'Event',
  description: 'A Event',
  fields: () => ({
   _id: {
      type: GraphQLString,
      description: 'The id of the event.',
    },
     id: {
      type: GraphQLString,
      description: 'The id of the event.',
    },
    title: {
      type: GraphQLString,
      description: 'The title of the event.',
    },
     description: {
      type: GraphQLString,
      description: 'The description of the event.',
    },
    media:{
      type:new GraphQLList(mediaType),
      description:'List of media',   
    },
    location:{
      type:new GraphQLList(locationType),
      description:'List of location',   
    }  
  })
});

// Media Type

export var mediaType = new GraphQLObjectType({
  name: 'Media',
  description: 'A Media',
  fields: () => ({
   _id: {
      type: GraphQLString,
      description: 'The id of the event.',
    },
   url:{
      type: GraphQLString,
      description: 'The url of the event.',
    },
    mediaType:{
      type: GraphQLString,
      description: 'The mediaTypa of the event.',
    }
  })
});

 // Location Type

export var locationType = new GraphQLObjectType({
  name: 'Location',
  description: 'A location',
  fields: () => ({
  _id: {
      type: GraphQLString,
      description: 'The id of the event.',
    },
    address:{
      type: GraphQLString,
      description: 'The address.',
    },
    state:{
      type: GraphQLString,
      description: 'The state.',
    },
    city:{
      type: GraphQLString,
      description: 'The city.',
    },
    Zip:{
      type: GraphQLString,
      description: 'The Zip code.',
    },
    country:{
      type: GraphQLString,
      description: 'The country.',
    }
  })
});

Schéma de mangouste:

var EventSchema = new mongoose.Schema({
  title: {
        required: true,
        type: String,
        trim: true,
        match: /^([\w ,.!?]{1,100})$/
    },
    description: {
        required: false,
        type: String,
        trim: true,
        match: /^([\w ,.!?]{1,100})$/
    },
    media: [{
        url: {
            type: String,
            trim: true
        },
        mediaType: {
            type: String,
            trim: true
        }
    }],
    location: [{
            address: {
                type: String
            },
            city: {
                type: String
            },
            state: {
                type: String
            },
            Zip: {
                type: String
            },
            country: {
                type: String
            }
    }]
})

Type de mutation:

 addEvent: {
        type: EventType,
        args: {

        _id: {
          type: GraphQLString,
          description: 'The id of the event.',
        },
        title: {
          type: GraphQLString,
          description: 'The title of the event.',
        },
        description: {
          type: GraphQLString,
          description: 'The description of the event.',
        },
        media:{
          type:new GraphQLList(mediaType),
          description:'List of media',   
        },
        location:{
          type:new GraphQLList(locationType),
          description:'List of media',   
        },
        created: {
          type: GraphQLInt,
          description: 'The created of the user.',       
        } 
         },
      resolve: (obj, {title,description,media,location,created,_id}) => {

        let toCreateEvent = {
          title,
          description,
          created:new Date(),
          start: new Date(),
          media,
          location,
          _id,
        };

         return mongo()
            .then(db => {
              return  new Promise(
                function(resolve,reject){
              let collection = db.collection('events');
                  collection.insert(toCreateEvent, (err, result) => {
                    db.close();

                    if (err) {
                      reject(err);
                      return;
                    }
                    resolve(result);
                  });
            })
          });
       }
     }
22
Mahesh

Votre problème est que lorsque vous définissez des mutations, tous les types doivent être des types d'entrée, d'où l'erreur que vous obtenez "Must be input type". Donc ici (à partir de votre mutation):

media:{
  type:new GraphQLList(mediaType),
  description:'List of media',   
},
location:{
  type:new GraphQLList(locationType),
  description:'List of media',   
},

GraphQLList, mediaType et locationType doivent être des types d'entrée.

GraphQLList est déjà un type d'entrée (voir ici https://github.com/graphql/graphql-js/blob/master/src/type/definition.js#L74-L82 pour voir la liste des types GraphQL considérés comme types d'entrée).

Cependant, vos types mediaType et locationType sont de type GraphQLObjectType, qui n'est pas un type d'entrée mais si vous regardez à nouveau la liste des types d'entrée: https: //github.com/graphql/graphql-js/blob/master/src/type/definition.js#L74-L82 , vous trouverez GraphQLInputObjectType qui est un type d'entrée d'objet, donc, ce que vous devez faire est de remplacer mediaType et locationType par leur version "input".

Ce que je suggère de faire est de créer mediaInputType et locationInputType qui aurait la même structure de champ que mediaType et locationType mais créé avec new GraphQLInputObjectType({... au lieu de new GraphQLObjectType({... et utilisez-les dans votre mutation.

J'ai rencontré le même problème et je l'ai résolu comme ça, n'hésitez pas à commenter si vous avez des questions.

22
adriantoine

J'ai rencontré le même problème - je ne savais pas comment spécifier un tableau d'objets dans la définition d'entrée. Donc, pour ceux qui veulent voir une solution de schéma "texte":

type Book {
  title: String!
}

d'avoir un tableau de livres dans votre type d'entrée

input AuthorInput {
  name: String!
  age: Int!
}

vous ne pouvez pas simplement ajouter books: [Book!] à l'intérieur de l'instruction d'entrée, vous aurez besoin de créer délibérément un type d'entrée contenant les champs nécessaires (dupliquez si vous le souhaitez):

input BookInput {
  title: String!
}

et puis vous pouvez:

input AuthorInput {
  name: String!
  age: Int!
  books: [BookInput!]
}
4
bora89