web-dev-qa-db-fra.com

Mutation GraphQL qui accepte un tableau de taille dynamique et de types scalaires communs en une seule demande

Je dois pouvoir créer un utilisateur et ajouter ses films préférés (un tableau d'objets avec une référence à la collection Movies et sa note personnelle pour chaque film) en une seule demande.

Quelque chose qui pourrait ressembler à ça (pseudocode)

var exSchema = `
 type Mutation {
    addUser(
        name: String!
        favMovies: [{ movie: String! #ref to movies coll
                      personal_rating: Int! # this is different for every movie
                   }]
    ) : User
 }
...
`

Quelle est la manière graphql de le faire en une seule demande? Je sais que je peux obtenir le résultat avec plusieurs mutations/demandes, mais je voudrais le faire en une seule.

13
octohedron

Vous pouvez passer un tableau comme celui-ci

var MovieSchema = `
  type Movie {
   name: String
  }
  input MovieInput {
   name: String
  }
  mutation {
   addMovies(movies: [MovieInput]): [Movie]
  }
`

Ensuite, dans votre mutation, vous pouvez passer un tableau comme

mutation {
  addMovies(movies: [{name: 'name1'}, {name: 'name2'}]) {
    name
  }
}

Je n'ai pas testé le code mais vous avez l'idée

28
octohedron

J'ai trouvé cette solution simple - AUCUN JSON utilisé. Une seule entrée est utilisée. J'espère que cela aidera quelqu'un d'autre.

J'ai dû ajouter à ce type:

type Option {
    id: ID!
    status: String!
    products: [Product!]!
}

Nous pouvons ajouter au type de mutation et ajouter une entrée comme suit:

type Mutation {
    createOption(data: [createProductInput!]!): Option!
    // other mutation definitions
}

input createProductInput {
    id: ID!
    name: String!
    price: Float!
    producer: ID!
    status: String
}

Le résolveur suivant pourrait alors être utilisé:

const resolvers = {
    Mutation: {
      createOption(parent, args, ctx, info) {

        const status = args.data[0].status;

        // Below code removes 'status' from all array items not to pollute DB.
        // if you query for 'status' after adding option 'null' will be shown. 
        // But 'status': null should not be added to DB. See result of log below.
        args.data.forEach((item) => {
            delete item.status
        });

        console.log('args.data - ', args.data);

        const option = {
            id: uuidv4(),
            status: status,  // or if using babel    status,
            products: args.data
        }

        options.Push(option)

        return option
      },
    // other mutation resolvers
    }

Vous pouvez maintenant l'utiliser pour ajouter une option (STATUS est tiré du premier élément du tableau - il peut être annulé):

mutation{
  createOption(data:
    [{
            id: "prodB",
            name: "componentB",
            price: 20,
            producer: "e4",
            status: "CANCELLED"
        },
        {
            id: "prodD",
            name: "componentD",
            price: 15,
            producer: "e5"
        }
    ]
  ) {
    id
    status
    products{
      name
      price
    }
  }
}

Produit:

{
  "data": {
    "createOption": {
      "id": "d12ef60f-21a8-41f3-825d-5762630acdb4",
      "status": "CANCELLED",
      "products": [
        {
          "name": "componentB",
          "price": 20,
        },
        {
          "name": "componentD",
          "price": 15,
        }
      ]
    }
  }
}

Inutile de dire que pour obtenir un résultat supérieur, vous devez ajouter:

type Query {
    products(query: String): [Product!]!
    // others
}

type Product {
    id: ID!
    name: String!
    price: Float!
    producer: Company!
    status: String
}

Je sais que ce n'est pas la meilleure façon, mais je n'ai pas trouvé de moyen de le faire dans la documentation.

5
Ula

J'ai fini par analyser manuellement le schéma correct, car les tableaux JavaScript et les chaînes JSON.stringify n'étaient pas acceptés comme format de schéma graphQL.

const id = 5;
const title = 'Title test';

let formattedAttachments = '';
attachments.map(attachment => {
  formattedAttachments += `{ id: ${attachment.id}, short_id: "${attachment.shortid}" }`;      
  // { id: 1, short_id: "abcxyz" }{ id: 2, short_id: "bcdqrs" }
});

// Query
const query = `
  mutation {
    addChallengeReply(
      challengeId: ${id}, 
      title: "${title}", 
      attachments: [${formattedAttachments}]
    ) {
      id
      title
      description
    }
  }
`;
1
CoredusK

Passez-les sous forme de chaînes JSON. C'est ce que je fais.

0
Abhishiv Saxena

Ce que je comprends de votre exigence, c'est que si vous avez le code suivant

const user = {
    name:"Rohit", 
    age:27, 
    marks: [10,15], 
    subjects:[
        {name:"maths"},
        {name:"science"}
    ]
};

const query = `mutation {
        createUser(user:${user}) {
            name
        }
}`

vous devez obtenir quelque chose comme

"mutation {
        createUser(user:[object Object]) {
            name
        }
}"

au lieu de l'attendu

"mutation {
        createUser(user:{
            name: "Rohit" ,
            age: 27 ,
            marks: [10 ,15 ] ,
            subjects: [
                {name: "maths" } ,
                {name: "science" } 
                ] 
            }) {
            name
        }
}"

Si c'est ce que vous vouliez atteindre, alors gqlast est une fonction de balise Nice que vous pouvez utiliser pour obtenir le résultat attendu

Prenez simplement le fichier js de ici et utilisez-le comme:

const user = {
    name:"Rohit", 
    age:27, 
    marks: [10,15], 
    subjects:[
        {name:"maths"},
        {name:"science"}
    ]
};

const query = gqlast`mutation {
        createUser(user:${user}) {
            name
        }
}`

Le résultat stocké dans la variable query sera:

"mutation {
        createUser(user:{
            name: "Rohit" ,
            age: 27 ,
            marks: [10 ,15 ] ,
            subjects: [
                {name: "maths" } ,
                {name: "science" } 
                ] 
            }) {
            name
        }
}"
0
Rohit Chopra