Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GraphQL Basics course] [Main Task] [Sanchit] #7

Open
atherdon opened this issue Jul 4, 2018 · 20 comments
Open

[GraphQL Basics course] [Main Task] [Sanchit] #7

atherdon opened this issue Jul 4, 2018 · 20 comments
Assignees

Comments

@atherdon
Copy link
Member

atherdon commented Jul 4, 2018

Please start by reading the documentation, related to GraphQL: https://www.howtographql.com/
After reading each chapter - please briefly explain to me here what did you learn from it.
Format(example):

Chapter 1: Intro (https://graphql.org/learn/)

"It's covering the basics of graphql"
Questions: "How i can run it at my local PC"?


@sanchit94 - it's your task

@sanchit94
Copy link
Collaborator

Okay, working on it! :)

@atherdon
Copy link
Member Author

atherdon commented Jul 5, 2018

As you more familiar with our github workflow, please start reading first chapters asap and put here your progress. I think this will motivate our other team members to start a race. just a little competition does not harm, right? let's this will be our secret :)

@sanchit94
Copy link
Collaborator

Please add me as a collaborator to this one @atherdon. For now I have forked this repo.

@sanchit94
Copy link
Collaborator

sanchit94 commented Jul 5, 2018

@atherdon Okay so last night I learnt a lot about GraphQL, how it differs from the conventional RESTful APIs and some basic concepts of GraphQL. Basically it provides a single end-point which have ability to handle resource, contrary to REST which just hands over data from the resource and has multiple end-points. To use GraphQL, we need to define a Schema first, which is the raw structure in which data is stored. We also need a resolver function to maybe tell GraphQL how to fetch data, but that is not very clear with my current understanding.

@sanchit94
Copy link
Collaborator

I have added a file server.js and was able to run in on command line by doing node server.js.
For setting the project up, I used this [https://graphql.org/graphql-js/]

@atherdon
Copy link
Member Author

atherdon commented Jul 5, 2018

please follow this link: https://github.com/GroceriStar/playing-with-graphql/invitations

Please hold on with an actual coding part. I mean at first i want to understand that you know main features and basics.

then we'll build some sort of pseudo-code in graphql schemas in order to practice it and discuss database improvements. main feature in GraphQL that you can easily extend the database - this is what hold my project back with REST API approach.

we have at least few databases and i prepare some plan so we actually will not just replicate logic of our current API servers, but we also will extend and update it.
Some details please read here: https://medium.com/groceristar/chickenkyiv-database-logic-intro-part-1-b2c449d92aa3
https://medium.com/groceristar/chickenkyiv-database-logic-simple-samples-part-2-1ee3ccc6b3d
https://medium.com/groceristar/chicken-kyiv-recipe-db-schema-part3-b80f33ec5d96

@sanchit94
Copy link
Collaborator

sanchit94 commented Jul 5, 2018

@atherdon Thanks for providing me some perspective over the project, and yes I too realized that getting the basics of this is important. Specially for me because I have not worked much with APIs or back-end.

@atherdon
Copy link
Member Author

atherdon commented Jul 5, 2018

i adore your pro-activity - don't want to loose it. But let's strict to main plan. this will be also more easy for me to follow your progress. So please check description of this task again - and try to explain to me for each sections at graph-ql intro what do you learn. this will raise a discussion between you and me, and we'll be able to start actual work at graphQl schema. when it'll looks cool - we'll start to test it.

Because actually - we have everything for it. We have a mongodb, we have imported data to it. so only schemas holding us back.

Btw, can you move that links to readme(please separate them from trash links that i store there), so other developers will have access to them too

@atherdon
Copy link
Member Author

atherdon commented Jul 5, 2018

"url": "mongodb://heroku_p3w65n77:[email protected]:35065/heroku_p3w65n77",
"name": "groceryDS",

"searchDS": {
"url": "mongodb://heroku_ghbnqks1:[email protected]:39994/heroku_ghbnqks1",


"recipeDS": {
"url": "mongodb://heroku_p0dxgncb:[email protected]:47052/heroku_p0dxgncb",


This is links to our mongo databases - please move them to readme too

@sanchit94
Copy link
Collaborator

This chapter talks about how GraphQL service is created. Basically we first define types and then fields on those types. Also the datatype on each field is specified here. We also provide functions for each field on each type so that we can retrieve that data(, or do something with it). It also describes how to send a query to receive data, which is very simple and flexible way to do so.

@atherdon
Copy link
Member Author

atherdon commented Jul 5, 2018

which chapter?

@atherdon
Copy link
Member Author

atherdon commented Jul 5, 2018

please follow this template:

Chapter 1: Intro (https://graphql.org/learn/)

"This chapter talks about how GraphQL service is created. Basically we first define types and then fields on those types. Also the datatype on each field is specified here. We also provide functions for each field on each type so that we can retrieve that data(, or do something with it). It also describes how to send a query to receive data, which is very simple and flexible way to do so."

@sanchit94
Copy link
Collaborator

sanchit94 commented Jul 6, 2018

Chapter 2: Queries and Mutation (https://graphql.org/learn/queries/)

  1. Query: Learnt how to structure query in GraphQL. In a query we can traverse our data and specify the field whose data we need, and the response is very similar to our query(, it is the query with the required data). We can ask for any field types, including Objects too, and we can go inside them by using brackets{ } and specify the required fields.
  2. Arguments: We can also pass arguments in the query for a field, to declaratively fetch data that is required.
  3. Aliases: Used for querying the same field with different arguments. Quite clear with the example there.
  4. Fragments: Cool feature, for modularising the query. Construct a set of fields, and then you can pass them into your query by ...fragmentName.
  5. Operation types: Any action is an operation. Operation can be of types query, mutation and subscription. Operations have types and name.
  6. Variables: variables can be also defined, for passing dynamic arguments in an operation. Variables can also be assigned default values.
  7. Directives: Used for dynamically manipulating the structure of the query. Like you can include or exclude some field by adding conditional statement on variables.
  8. Mutation: This is operation type for modifying data on the server. Cool thing is that you can query from the same data that you mutated. One thing is not clear however, in the example:
    mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) { createReview(episode: $ep, review: $review) { stars commentary } }
    Shouldn't it be something like:
    mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) { createReview(episode: $ep, review: $review) { review { stars commentary } } }
    Anyways I think things will get clear as I move on with it.
  9. Inline Fragments: Useful for querying when we do not know the type that is going to return. We can ask for specific fields based on the types of the returned data.
  10. Meta Fields: __typename can be used to determine to the type of the returned data, which can then be used to select what we want from the data.

@atherdon
Copy link
Member Author

atherdon commented Jul 6, 2018

@sanchit94 perfect!

@atherdon
Copy link
Member Author

atherdon commented Jul 7, 2018

@sanchit94
Copy link
Collaborator

Done! 👍

@sanchit94
Copy link
Collaborator

sanchit94 commented Jul 8, 2018

Chapter 3: Schemas and Types (https://graphql.org/learn/schema/)

  1. Type System: GraphQL has a strongly typed system, and we explicitly define types on each field of the object in the schema definition. Types can be defined as in Object types using the type keyword, or they can be built-in scalar types. By this, we can have an idea of what to expect when a query is made. Types are also needed for validation of the query.
  2. Type Language: GraphQL has a uniques SDL(Schema Description Language) for describing schema of the GraphQL service.
  3. Object types and fields: An object type can have fields inside it, where each field can have a scalar type as it's type or another object type as it's type. Basically this is the way of implementing relational databases.
  4. Arguments: Every GraphQL field can have multiple arguments``, but they need to be explicitly passed by name. If an argument is optional we can assign a default value to it.
  5. Query and Mutation types: Every service has a query type which defines the entry-point for the GraphQL query. It may or may not have a mutation type. Defined using type keyword. Question: Can I only query data of fields for which I have a query type?
  6. Scalar types: These are the leaves of the query, the fields that have these types do not have a sub-field. GraphQL has following scalar types: Int, String, Float, Boolean, ID. We can also specify custom scalar types, using scalar keyword by doing scalar typeName
  7. Enumeration types: Special types of scalars where you can define a set of allowed values. Anything other than that will be an error during validation We can use enum keyword to define an 'enum'.
  8. Lists and Non-Null: While defining the type on a field, we can also apply type modifiers to extend our type. We can do String! to make the string type non-nullable. Once ! is added to the type, the server always expects a non-null value from that field. Second type modifier is List, where we can mark a field to return a list(kind of array) of values by wrapping [ ] around the type name.
    Both type modifiers can be flexibly combined according to need. Like we can do Numbers : [Int!] to indicate the Numbers field is a list of Int values, where each entry in the list is a non-null object. Although the list can be null itself. Numbers: [Int]! means the list is non-null, but a member of a list can be null. Numbers : [Int!]! means neither the list nor any member on the list is null.
  9. Interfaces: Interface is an abstract type, which includes a list of fields that an object type must include if it implements that interface, while that object type can have additional fields too. Similar to inheritance.
    When a type inherits from an interface, then the fields on the interface can be directly accessed, but the object-specific fields must be accessed by using in-line fragment.
  10. Union types: A type whose equivalent is an OR of specified types. This means an object of Union types can be either of the types in the description. For e.g. union Breakfast = Sandwiches | Omelet | Oats means that the union type Breakfast can be either of the types Sandwiches, Omelet or Oats. When querying union types, we should always use in-line fragments for each type(Sandwiches, Omelet, Oats) so that there is no error.
  11. Input types: We can pass complex objects as type to a field. For this we first need to create those objects using the input keyword. Then we can start passing them. Useful for mutations, where we pass these input types to the object, we can even pass them as variables. Pretty cool! :)

@sanchit94
Copy link
Collaborator

sanchit94 commented Jul 9, 2018

Chapter 4: Validation(https://graphql.org/learn/validation/)

Validation is done using type system to determine whether a query is valid or not. So there are some rules that we need to follow.
There are a few rules that are mentioned in the documentation:

  1. A fragment cannot refer to itself: As this would create a cycle, sort of recurrence but there is no exit from it. So doing this will lead to an invalid query.
    For e.g.
food {  
   ...details
   sameCuisine {
            ...details
            sameCuisine {
                  ...details
                 }
          }
   }

fragment details on foodItems {
name
cuisine
}

This valid query, but if we try to implement the same using a fragment like

fragment details on foodItems {
name
cuisine
...details
}

then it is invalid, as a fragment is calling itself.

  1. When querying fields, only query for fields that are present in that type: Self explanatory, if we search for a field that is not present in the type, then it will be an error.

  2. If the query returns something other than a scalar or enum, like an object type, then we need to specify which fields we want from that object. If we fail to do so the query is invalid. Question: What is the best practice in cases we need info of all fields? Do we make an enum?

  3. If a field is scalar, we cannot query any fields inside it.

  4. If our type implements an interface, then we can directly query only the fields on the interface. For querying type-specific fields, we can either use inline fragments or create a fragment on the type.

@sanchit94
Copy link
Collaborator

sanchit94 commented Jul 13, 2018

Chapter 5: Execution (https://graphql.org/learn/execution/)

GraphQL query is executed after Validation which resolves to a JSON response, generally.
Each field in a query has a corresponding resolver method which is a function that tells the service how to handle the query. This means it returns the type that is expected, and if that type is a scalar type, it would return the value. This completes the execution. A query always ends at the scalar type.

Root fields and resolver: Root type is the top level of the query. In the example given in the documentation, the root query has a resolver function human, which takes four arguments:

  1. obj: The previous object, which we have to enter in order to resolve the query. This is not need for root resolver function.
  2. args: The argument provided, for e.g. id, or name.
  3. context: Haven't got much idea what this is, but I think we will get to know more about the details of this as we move along. Maybe it contains methods to fetch data, like getHumantById.
  4. info: Containing field specific information and schema details.

Asynchronous Resolvers: The query does not always return data, but it returns a Promise, which can be passed around as a token even if we do not have the value yet, in hope that when the Promise is fulfilled, it will provide the data. During execution GraphQL waits for the Promises to resolve(or be rejected).

Trivial Resolvers: Trivial resolver is one that simply fetched the value of the field. Some libraries let us omit these trivial resolvers and do this for us by default.

Scalar Coercion: GraphQL can use scalars(or numbers) internally to store values of some objects. Once the query is made, the scalar is returned and the corresponding value to this scalar that is mapped can be returned.

List Resolvers: When a field type is a list, then GraphQL will return a list of Promises on that.

Producing the result: As the fields are resolved, the result is displayed in form of key-value pair(JSON) which looks like the query we requested.

@atherdon
Copy link
Member Author

atherdon commented Feb 6, 2019

btw, we're continue our work on grapqhql server, maybe this will be also interesting for you as backend development. repo: https://github.com/GroceriStar/graphql-server

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants