Search code examples
mongodbgraphqlreact-apollo

GraphQL query with variables results in 400 error


I have been trying to get my graphQL query to pass variables to my back end. I have tested my server side resolvers and they perform well when static data is coded. My front end doesn't ever reach the resolvers as far as i can tell with a console log as the first action of the resolver. What direction should I be looking in I have been searching for 3 days now so tried alot of different senarios

When you remove both arguments, The query works as expected, returning a random movie from the database. However with the arguments I expect to get a random movie from the year selected by the user, but I receive "Response not successful:Recieved status code 400".

I have this same issue with the other page where a user can enter year, genre, and language to get a list of movies. In Queries.js:

export const QUERY_RANDOM_MOVIE = gql`
  query RandomMovie($year: String) {
    randmovie(year: $year) {
      _id
      title
      plot
      year
      poster
      cast
      directors
      released
    }
  }
`;

In Random.js:

export default function Random() {
  const [ year, setYear ] = useState(1950);
  const { loading, error, data, refetch } =
    useQuery(QUERY_RANDOM_MOVIE, { variables: { year: year }});
  if (loading) return 'Loading...';
  if (error) return `Error! ${error.message}`;

My Schema:

    const { Schema, model } = require('mongoose');

    const Award = new Schema({
        wins: {type:Number},
        nominations: {type:Number},
        text: {type:String},
    });

    const Imdb = new Schema({
       rating:{type:Number},
       votes:{type:Number}, 
       id:{type:Number},
    });

    const View = new Schema({
        rating:{type:Number},
        numReviews:{type:Number},
    });

    const Tomato = new Schema({
       viewer:[View],
       production:{type:String},
       lastUpdated:{type:Date, default:Date.now},
    });


    const movieSchema = new Schema (
        {
        plot: {
            type: String,
            // required:true,
        },
        genres: [
            {
            type: String,
            // required:true,
            },
        ],
        runtime: {
            type: Number,
            // required:true,
        },
        cast: [
            {
                type: String,
            },
        ],
        poster: {
            type: String,
            required:false,
        },
        title:{
            type:String,
            // required:true, 
        },
        fullplot: {
            type: String,
            required: false,
        },
        languages: [
            {
            type: String,
            required: false,
            },  
        ],
        released: {
            type: Date,
            // required: true,
        },
        directors:[
            {
                type: String, 
                // required: true,
            },
        ],
        rated: {
            type: String,
            required: false,
        },
        awards:[Award],
        lastupdated: {
            type: Date,
            default: Date.now,
        },
        year:{
            type:Number,
        },
        imdb:[Imdb],
        countries:[
            {
            type: String,
            },
        ],
        tomatoes:[Tomato],
        writers:[
            {
                type: String,
            },
        ],
        type:{
            type:String,
        },
        plot_embedding:[
            {
                type: Number,
            },
        ],
        metacritic:{
            type: Number,
        },
      },
     );

     const Movie = model('Movie', movieSchema)

     module.exports = Movie;

Adding resolver from server side. The year is hard coded and works here, but since I cannot pass the year from the front end, this will not work with the varible year:

    randmovie: async(parent, year) => {
         const randmovie=  await Movie.aggregate(
          [{$match:{year:1950}},
            { $sample: { size: 1 } }]);
          console.log(randmovie);
          return randmovie[0]
        },

The typeDefs.js:

const typeDefs = `
  type Movie {
    _id: ID
    plot: String
    genres: [String]
    runtime: Int
    cast: [String]
    poster: String
    title: String
    fullplot: String
    languages: [String]
    released: String
    directors: [String]
    rated: String
    awards: [Award]
    lastupdated: String
    year: String
    imdb: [Imdb]
    countries: [String]
    tomatoes: [Tomato]
    writers: [String]
    type: String
    plot_embedding:[Int]
    metacritic: Int
}

  type Award {
   id: ID
   wins: Int
   nominations: Int
   text: String
}

  type Imdb {
    rating: Int
    votes: Int 
    id: Int
}

  type Tomato {
    viewer: [View]
    production: String
    lastUpdated: String
}

  type View {
    rating:Int
    numReviews:Int
}

type Query {
  # get all movies
  movies: [Movie]!
  # get a random movie
  randmovie: Movie
  # get a random movie with params
  randfocusedmovie: Movie
  # get list of all genres
  genrelist: [Movie]
  # get list of all languages
  languagelist: [Movie]
  #get movie list with params
  movieswithparams: [Movie]
}
`;

module.exports = typeDefs;

Solution

  • Your randmovie query type doesn't specify any parameters. Where you have:

    type Query {
      randmovie: Movie
    }
    

    You need:

    type Query {
      randmovie(year: Int): Movie
    }