Konstantin Schütte
Konstantin Schütte

Reputation: 1009

GraphQL relations

I'm following the tutorials of Academind, so this video is my current standpoint: https://www.youtube.com/watch?v=MRrcUQhZwBc

So my current code is:

const express = require('express');
const bodyParser = require('body-parser');
const graphqlHttp = require('express-graphql');
const { buildSchema } = require('graphql');
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');

const Event = require('./models/event');
const User = require('./models/user');

const app = express();

app.use(bodyParser.json());

app.use(
  '/graphql',
  graphqlHttp({
    schema: buildSchema(`
        type Event {
          _id: ID!
          title: String!
          description: String!
          price: Float!
          date: String!
        }

        type User {
          _id: ID!
          email: String!
          password: String
        }

        input EventInput {
          title: String!
          description: String!
          price: Float!
          date: String!
        }

        input UserInput {
          email: String!
          password: String!
        }

        type RootQuery {
            events: [Event!]!
        }

        type RootMutation {
            createEvent(eventInput: EventInput): Event
            createUser(userInput: UserInput): User
        }

        schema {
            query: RootQuery
            mutation: RootMutation
        }
    `),
    rootValue: {
      events: () => {
        return Event.find()
          .then(events => {
            return events.map(event => {
              return { ...event._doc, _id: event.id };
            });
          })
          .catch(err => {
            throw err;
          });
      },
      createEvent: args => {
        const event = new Event({
          title: args.eventInput.title,
          description: args.eventInput.description,
          price: +args.eventInput.price,
          date: new Date(args.eventInput.date),
          creator: '5c0f6dcde049d205fa2471dc'
        });
        let createdEvent;
        return event
          .save()
          .then(result => {
            createdEvent = { ...result._doc, _id: result._doc._id.toString() };
            return User.findById('5c0f6dcde049d205fa2471dc');
          })
          .then(user => {
            if (!user) {
              throw new Error('User not found.');
            }
            user.createdEvents.push(event);
            return user.save();
          })
          .then(result => {
            return createdEvent;
          })
          .catch(err => {
            console.log(err);
            throw err;
          });
      },
      createUser: args => {
        return User.findOne({ email: args.userInput.email })
          .then(user => {
            if (user) {
              throw new Error('User exists already.');
            }
            return bcrypt.hash(args.userInput.password, 12);
          })
          .then(hashedPassword => {
            const user = new User({
              email: args.userInput.email,
              password: hashedPassword
            });
            return user.save();
          })
          .then(result => {
            return { ...result._doc, password: null, _id: result.id };
          })
          .catch(err => {
            throw err;
          });
      }
    },
    graphiql: true
  })
);

mongoose
  .connect(
    `mongodb+srv://${process.env.MONGO_USER}:${
      process.env.MONGO_PASSWORD
    }@cluster0-ntrwp.mongodb.net/${process.env.MONGO_DB}?retryWrites=true`
  )
  .then(() => {
    app.listen(3000);
  })
  .catch(err => {
    console.log(err);
  });

I have currently created events with a relation to a user. Now I want to get all events from a user. Therefore I've found this article: https://devhints.io/graphql I want to use the "Lookups", so my code for a request would be:

{
  events(_id: "5da717be4330150430fd770e") { _id }
}

But I am recieving this error:

{
  "errors": [
    {
      "message": "Unknown argument \"id\" on field \"events\" of type \"RootQuery\".",
      "locations": [
        {
          "line": 2,
          "column": 10
        }
      ]
    }
  ]
}

But what do I need to do to get it working?

Upvotes: 1

Views: 338

Answers (1)

Alex Pappas
Alex Pappas

Reputation: 2678

You have no Query for getting specific Event with its id. Your "events" query does not accept any args and is expected to return an array of Events.

type RootQuery {
   events: [Event!]!
}

See the following example from the docs

type Query {
  human(id: ID!): Human
}

type Human {
  name: String
  appearsIn: [Episode]
  starships: [Starship]
}

enum Episode {
  NEWHOPE
  EMPIRE
  JEDI
}

type Starship {
  name: String
}

In order to describe what happens when a query is executed, let's use an example to walk through.

{
  human(id: 1002) {
    name
    appearsIn
    starships {
      name
    }
  }
}

Result

{
  "data": {
    "human": {
      "name": "Han Solo",
      "appearsIn": [
        "NEWHOPE",
        "EMPIRE",
        "JEDI"
      ],
      "starships": [
        {
          "name": "Millenium Falcon"
        },
        {
          "name": "Imperial shuttle"
        }
      ]
    }
  }
}

Take note of the example

type Query {
  human(id: ID!): Human
}

In your case, you will have to make something like that from above:

type Event{
  event(id: ID!): Event
}

Upvotes: 3

Related Questions