Fateme Ahmadi
Fateme Ahmadi

Reputation: 344

how can search a specific user in graphql

I write this code in nodejs and graphQL server. I had 2 collection in mongodb; Stars and Movies. Stars save information about Stars that act in top movies. and Movie collection save information about each movie. when i query movie this code return to me all movie that saved in my database. but how can I modified this code that when i search stars or movies by a specific id this code can return to me a single user or star?

this is my schema :

    const {
    GraphQLSchema,
    GraphQLObjectType,
    GraphQLString,
    GraphQLInt,
    GraphQLNonNull,
    GraphQLList,
    GraphQLFloat
} = require("graphql");
const {Movie, User} = require('/home/fateme/imdb_final/db')


const starType = new GraphQLObjectType({
    name: "UserType",
    fields: {
      name: {
        type: GraphQLString,
        async resolve(objId) {
            const starFind = await User.findOne({ _id: objId})
            return starFind.name
        }
      },
      imdbId: {
        type: GraphQLString,
        async resolve(objId) {
            const starFind = await User.findOne({ _id: objId}) 
            return starFind.imdbId
        }
      }
    }
  });

const movieType = new GraphQLObjectType({
    name: "MovieType",
    fields: {
      title: {
        type: GraphQLString,
        async resolve(objId) {
            const movieFind = await Movie.findOne({ _id: objId._id})
            return movieFind.title
        }
      },
      year: {
        type: GraphQLInt,
        async resolve(objId) {
            const movieFind = await Movie.findOne({ _id: objId._id})
            return movieFind.year
        }
      },
      rate: {
        type: GraphQLFloat,
        async resolve(objId) {
            const movieFind = await Movie.findOne({ _id: objId._id})
            return movieFind.rating
        }
      },
      // rank: {
      //   type: GraphQLInt,
      //   async resolve(objId) {
      //       const movieFind = await Movie.findOne({ _id: objId._id})
      //       return movieFind.rank
      //   }
      // },
      director: {
        type: starType,
        async resolve(objId) {
            return objId.director

            // return userFind.name
        }
      },
      stars: {
        type: GraphQLList(starType),
        async resolve(objId) {
            return objId.stars

            // return userFind.name
        }
      },
    }
  });


  const queryType = new GraphQLObjectType({
    name: 'Query',
    fields: () => ({

        users: {
            type: GraphQLList(starType),
            async resolve() {

              const allStar = await User.find({})
              return  allStar._id
            }
          },

      movies: {
        type: GraphQLList(movieType),
        async resolve() {

            const allMovie = await Movie.find({})
            return  allMovie
          } 
        },
    })
  });

  const schema = new GraphQLSchema({
    query: queryType
  });

  module.exports = schema;

Upvotes: 0

Views: 1201

Answers (1)

David Maze
David Maze

Reputation: 159428

In graphql-js, you can set up an object type that's backed by a JavaScript class object. If you do that, you don't need to provide separate resolvers for class methods; a GraphQL field that matches a class method will just directly call that method and use the results.

The GraphQL server library you're using will take responsibility for unpacking a list-of-objects response to a GraphQL list type, and dispatching resolver calls to a specific object from that list as required.

In any implementation language, a good general pattern for GraphQL is this:

  • Root-level resolvers (your Query and Mutation types) find specific objects; and

  • Object-level resolvers (in your example, UserType and MovieType) act on known specific objects that already have a programming-language-level representation.

That is, if you're in a resolver function for some specific type, you don't need to look up that object again; you should already have it (in your case from the root query resolvers).

Your resolver implementations make it clear that your objects already have fields that match the GraphQL field names, so the two changes you need to make are making the root-level resolver provide the specific object:

const root = {
  users: async () => User.find({}),
  movies: async () => Movie.find({})
}

and just provide a schema that directly reflects the pre-existing object layout:

const schema = buildSchema(`
  type UserType {
    name: String
    imdbId: String
  }
  type MovieType {
    title: String
    year: Int
    rating: Float
    # rank: Int
    director: StarType
    stars: [StarType]
  }
  type Query {
    users: [UserType]
    movies: [MovieType]
  }
`)

For the code you've shown, nothing requires a custom resolver, except that you try to rename the rating field to rate. In graphql-js I believe you need to provide an actual object that has the actual field names you want, and I've found it often makes sense to have a separate set of objects that directly reflect the GraphQL API that you want.

In my experience, if it's possible to use the GraphQL schema language, you should do so: it is much more compact and readable than an object-based representation of the same types.

Upvotes: 2

Related Questions