{"data":{"published":true,"body":"---\nsidebar: auto\n---\n# Guide to Super Graph\n\nSuper Graph is a service that instantly and without code gives you a high performance and secure GraphQL API. Your GraphQL queries are auto translated into a single fast SQL query. No more spending weeks or months writing backend API code. Just make the query you need and Super Graph will do the rest. \n\nSuper Graph has a rich feature set like integrating with your existing Ruby on Rails apps, joining your DB with data from remote APIs, Role and Attribute based access control, Support for JWT tokens, DB migrations, seeding and a lot more.\n\n\n## Features\n\n* Role and Attribute based access control\n* Works with existing Ruby\\-On\\-Rails apps\n* Automatically learns database schemas and relationships\n* Full text search and aggregations\n* Rails authentication supported \\(Redis, Memcache, Cookie\\)\n* JWT tokens supported \\(Auth0, etc\\)\n* Join database with remote REST APIs\n* Highly optimized and fast Postgres SQL queries\n* GraphQL queries and mutations\n* A simple config file\n* High performance GO codebase\n* Tiny docker image and low memory requirements\n* Fuzz tested for security\n* Database migrations tool\n* Database seeding tool\n\n\n## Try the demo app\n\n```bash\n# clone the repository\ngit clone https://github.com/dosco/super-graph\n\n# setup the demo rails app & database and run it\ndocker-compose run rails_app rake db:create db:migrate db:seed\n\n# run the demo\ndocker-compose up\n\n# signin to the demo app (user1@demo.com / 123456)\nopen http://localhost:3000\n\n# try the super graph web ui\nopen http://localhost:8080\n\n```\n\n::: tip DEMO REQUIREMENTS\nThis demo requires `docker` you can either install it using `brew` or from the\ndocker website [https://docs.docker.com/docker\\-for\\-mac/install/](https://docs.docker.com/docker-for-mac/install/)\n:::\n\n#### Trying out GraphQL\n\nWe fully support queries and mutations. For example the below GraphQL query would fetch two products that belong to the current user where the price is greater than 10.\n\n#### GQL Query\n\n```graphql\nquery {\n users {\n id\n email\n picture : avatar\n password\n full_name\n products(limit: 2, where: { price: { gt: 10 } }) {\n id\n name\n description\n price\n }\n }\n}\n\n```\n\n#### JSON Result\n\n```json\n{\n \"data\": {\n \"users\": [\n {\n \"id\": 1,\n \"email\": \"odilia@west.info\",\n \"picture\": \"https://robohash.org/simur.png?size=300x300\",\n \"full_name\": \"Edwin Orn\",\n \"products\": [\n {\n \"id\": 16,\n \"name\": \"Sierra Nevada Style Ale\",\n \"description\": \"Belgian Abbey, 92 IBU, 4.7%, 17.4°Blg\",\n \"price\": 16.47\n },\n ...\n ]\n }\n ]\n }\n}\n\n```\n\n::: tip Testing with a user\nIn development mode you can use the `X-User-ID: 4` header to set a user id so you don't have to worries about cookies etc. This can be set using the _HTTP Headers_ tab at the bottom of the web UI.\n:::\n\nIn another example the below GraphQL mutation would insert a product into the database. The first part of the below example is the variable data and the second half is the GraphQL mutation. For mutations data has to always ben passed as a variable.\n\n```json\n{\n \"data\": { \n \"name\": \"Art of Computer Programming\",\n \"description\": \"The Art of Computer Programming (TAOCP) is a comprehensive monograph written by computer scientist Donald Knuth\",\n \"price\": 30.5\n }\n}\n\n```\n\n```graphql\nmutation {\n product(insert: $data) {\n id\n name\n }\n}\n\n```\n\n## Why Super Graph\n\nLet's take a simple example say you want to fetch 5 products priced over 12 dollars along with the photos of the products and the users that owns them. Additionally also fetch the last 10 of your own purchases along with the name and ID of the product you purchased. This is a common type of query to render a view in say an ecommerce app. Lets be honest it's not very exciting write and maintain. Keep in mind the data needed will only continue to grow and change as your app evolves. Developers might find that most ORMs will not be able to do all of this in a single SQL query and will require n\\+1 queries to fetch all the data and assembly it into the right JSON response.\n\nWhat if I told you Super Graph will fetch all this data with a single SQL query and without you having to write a single line of code. Also as your app evolves feel free to evolve the query as you like. In our experience Super Graph saves us hundreds or thousands of man hours that we can put towards the more exciting parts of our app.\n\n#### GraphQL Query\n\n```graphql\nquery {\n products(limit 5, where: { price: { gt: 12 } }) {\n id\n name\n description\n price\n photos {\n url\n }\n user {\n id\n email\n picture : avatar\n full_name\n }\n }\n purchases(\n limit 10, \n order_by: { created_at: desc } , \n where: { user_id: { eq: $user_id } }\n ) {\n id \n created_at\n product {\n id\n name\n }\n }\n}\n\n```\n\n#### JSON Result\n\n```json\n\n \"data\": {\n \"products\": [\n {\n \"id\": 1,\n \"name\": \"Oaked Arrogant Bastard Ale\",\n \"description\": \"Coors lite, European Amber Lager, Perle, 1272 - American Ale II, 38 IBU, 6.4%, 9.7°Blg\",\n \"price\": 20,\n \"photos: [{\n \"url\": \"https://www.scienceworld.ca/wp-content/uploads/science-world-beer-flavours.jpg\"\n }],\n \"user\": {\n \"id\": 1,\n \"email\": \"user0@demo.com\",\n \"picture\": \"https://robohash.org/sitaliquamquaerat.png?size=300x300&set=set1\",\n \"full_name\": \"Mrs. Wilhemina Hilpert\"\n }\n },\n ...\n ]\n },\n \"purchases\": [\n {\n \"id\": 5,\n \"created_at\": \"2020-01-24T05:34:39.880599\",\n \"product\": {\n \"id\": 45,\n \"name\": \"Brooklyn Black\",\n }\n },\n ...\n ]\n}\n\n```\n\n## Get Started\n\nSuper Graph can generate your initial app for you. The generated app will have config files, database migrations and seed files among other things like docker related files.\n\nYou can then add your database schema to the migrations, maybe create some seed data using the seed script and launch Super Graph. You're now good to go and can start working on your UI frontend in React, Vue or whatever.\n\n```bash\n# Download and install Super Graph. You will need Go 1.13 or above\ngit clone https://github.com/dosco/super-graph && cd super-graph && make install\n\n```\n\nAnd then create and launch you're new app\n\n```bash\n# create a new app and change to it's directory\nsuper-graph new blog; cd blog\n\n# setup the app database and seed it with fake data. Docker compose will start a Postgres database for your app\ndocker-compose run blog_api ./super-graph db:setup\n\n# and finally launch Super Graph configured for your app\ndocker-compose up\n\n```\n\nLets take a look at the files generated by Super Graph when you create a new app\n\n```bash\nsuper-graph new blog\n\n> created 'blog'\n> created 'blog/Dockerfile'\n> created 'blog/docker-compose.yml'\n> created 'blog/config'\n> created 'blog/config/dev.yml'\n> created 'blog/config/prod.yml'\n> created 'blog/config/seed.js'\n> created 'blog/config/migrations'\n> created 'blog/config/migrations/100_init.sql'\n> app 'blog' initialized\n\n```\n\n### Docker files\n\nDocker Compose is a great way to run multiple services while developing on your desktop or laptop. In our case we need Postgres and Super Graph to both be running and the `docker-compose.yml` is configured to do just that. The Super Graph service is named after your app postfixed with `_api`. The Dockerfile can be used build a containr of your app for production deployment.\n\n```bash\ndocker-compose run blog_api ./super-graph help\n\n```\n\n### Config files\n\nAll the config files needs to configure Super Graph for your app are contained in this folder for starters you have two `dev.yaml` and `prod.yaml`. When the `GO_ENV` environment variable is set to `development` then `dev.yaml` is used and the prod one when it's set to `production`. Stage and Test are the other two environment options, but you can set the `GO_ENV` to whatever you like \\(eg. `alpha-test`\\) and Super Graph will look for a yaml file with that name to load config from.\n\n### Seed\\.js\n\nHaving data flowing through your API makes building your frontend UI so much easier. When creafting say a user profile wouldn't it be nice for the API to return a fake user with name, picture and all. This is why having the ability to seed your database is important. Seeding cn also be used in production to setup some initial users like the admins or to add an initial set of products to a ecommerce store.\n\nSuper Graph makes this easy by allowing you to write your seeding script in plan old Javascript. The below file that auto\\-generated for new apps uses our built\\-in functions `fake` and `graphql` to generate fake data and use GraphQL mutations to insert it into the database.\n\n```javascript\n// Example script to seed database\n\nvar users = [];\n\nfor (i = 0; i < 10; i++) {\n var data = {\n full_name: fake.name(),\n email: fake.email()\n }\n\n var res = graphql(\" \\\n mutation { \\\n user(insert: $data) { \\\n id \\\n } \\\n }\", { data: data })\n\n users.push(res.user)\n}\n\n```\n\nYou can generate the following fake data for your seeding purposes. Below is the list of fake data functions supported by the built\\-in fake data library. For example `fake.image_url()` will generate a fake image url or `fake.shuffle_strings(['hello', 'world', 'cool'])` will generate a randomly shuffled version of that array of strings or `fake.rand_string(['hello', 'world', 'cool'])` will return a random string from the array provided.\n\n```\n// Person\nperson\nname\nname_prefix\nname_suffix\nfirst_name\nlast_name\ngender\nssn\ncontact\nemail\nphone\nphone_formatted\nusername\npassword\n\n// Address\naddress\ncity\ncountry\ncountry_abr\nstate\nstate_abr\nstatus_code\nstreet\nstreet_name\nstreet_number\nstreet_prefix\nstreet_suffix\nzip\nlatitude\nlatitude_in_range\nlongitude\nlongitude_in_range\n\n// Beer\nbeer_alcohol\nbeer_hop\nbeer_ibu\nbeer_blg\nbeer_malt\nbeer_name\nbeer_style\nbeer_yeast\n\n// Cars\nvehicle\nvehicle_type\ncar_maker\ncar_model\nfuel_type\ntransmission_gear_type\n\n// Text\nword\nsentence\nparagraph\nquestion\nquote\n\n// Misc\ngenerate\nboolean\nuuid\n\n// Colors\ncolor\nhex_color\nrgb_color\nsafe_color\n\n// Internet\nurl\nimage_url\ndomain_name\ndomain_suffix\nipv4_address\nipv6_address\nsimple_status_code\nhttp_method\nuser_agent\nuser_agent_firefox\nuser_agent_chrome\nuser_agent_opera\nuser_agent_safari\n\n// Date / Time\ndate\ndate_range\nnano_second\nsecond\nminute\nhour\nmonth\nday\nweekday\nyear\ntimezone\ntimezone_abv\ntimezone_full\ntimezone_offset\n\n// Payment\nprice\ncredit_card\ncredit_card_cvv\ncredit_card_number\ncredit_card_number_luhn\ncredit_card_type\ncurrency\ncurrency_long\ncurrency_short\n\n// Company\nbs\nbuzzword\ncompany\ncompany_suffix\njob\njob_description\njob_level\njob_title\n\n// Hacker\nhacker_abbreviation\nhacker_adjective\nhacker_ingverb\nhacker_noun\nhacker_phrase\nhacker_verb\n\n//Hipster\nhipster_word\nhipster_paragraph\nhipster_sentence\n\n// File\nextension\nmine_type\n\n// Numbers\nnumber\nnumerify\nint8\nint16\nint32\nint64\nuint8\nuint16\nuint32\nuint64\nfloat32\nfloat32_range\nfloat64\nfloat64_range\nshuffle_ints\nmac_address\n\n//String\ndigit\nletter\nlexify\nrand_string\nshuffle_strings\nnumerify\n\n```\n\n### Migrations\n\nEasy database migrations is the most important thing when building products backend by a relational database. We make it super easy to manage and migrate your database.\n\n```bash\nsuper-graph db:new create_users\n> created migration 'config/migrations/101_create_users.sql'\n\n```\n\nMigrations in Super Graph are plain old Postgres SQL. Here's an example for the above migration.\n\n```sql\n-- Write your migrate up statements here\n\nCREATE TABLE public.users (\n id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,\n full_name text,\n email text UNIQUE NOT NULL CHECK (length(email) < 255),\n created_at timestamptz NOT NULL NOT NULL DEFAULT NOW(),\n updated_at timestamptz NOT NULL NOT NULL DEFAULT NOW()\n);\n\n---- create above / drop below ----\n\n-- Write your down migrate statements here. If this migration is irreversible\n-- then delete the separator line above.\n\nDROP TABLE public.users\n\n```\n\nWe would encourage you to leverage triggers to maintain consistancy of your data for example here are a couple triggers that you can add to you init migration and across your tables.\n\n```sql\n-- This trigger script will set the updated_at column everytime a row is updated\nCREATE OR REPLACE FUNCTION trigger_set_updated_at()\nRETURNS TRIGGER SET SCHEMA 'public' LANGUAGE 'plpgsql' AS $$\nBEGIN\n new.updated_at = now();\n RETURN new;\nEND;\n$$;\n\n...\n\n-- An exmple of adding this trigger to the users table\nCREATE TRIGGER set_updated_at BEFORE UPDATE ON public.users\n FOR EACH ROW EXECUTE PROCEDURE trigger_set_updated_at();\n\n```\n\n```sql\n-- This trigger script will set the user_id column to the current\n-- Super Graph user.id value everytime a row is created or updated\nCREATE OR REPLACE FUNCTION trigger_set_user_id()\nRETURNS TRIGGER SET SCHEMA 'public' LANGUAGE 'plpgsql' AS $$\nBEGIN\n IF TG_OP = 'UPDATE' THEN\n new.user_id = old.user_id;\n ELSE\n new.user_id = current_setting('user.id')::int;\n END IF;\n\n RETURN new;\nEND;\n$$;\n\n...\n\n-- An exmple of adding this trigger to the blog_posts table\nCREATE TRIGGER set_user_id BEFORE INSERT OR UPDATE ON public.blog_posts\n FOR EACH ROW EXECUTE PROCEDURE trigger_set_user_id();\n\n```\n\n## How to GraphQL\n\nGraphQL \\(GQL\\) is a simple query syntax that's fast replacing REST APIs. GQL is great since it allows web developers to fetch the exact data that they need without depending on changes to backend code. Also if you squint hard enough it looks a little bit like JSON :smiley:\n\nThe below query will fetch an `users` name, email and avatar image \\(renamed as picture\\). If you also need the users `id` then just add it to the query.\n\n```graphql\nquery {\n user {\n full_name\n email\n picture : avatar\n }\n}\n\n```\n\nMultiple tables can also be fetched using a single GraphQL query. This is very fast since the entire query is converted into a single SQL query which the database can efficiently run.\n\n```graphql\nquery {\n user {\n full_name\n email\n }\n products {\n name\n description\n }\n}\n\n```\n\n### Fetching data\n\nTo fetch a specific `product` by it's ID you can use the `id` argument\\. The real name id field will be resolved automatically so this query will work even if your id column is named something like `product_id`.\n\n```graphql\nquery {\n products(id: 3) {\n name\n }\n}\n\n```\n\nPostgres also supports full text search using a TSV index. Super Graph makes it easy to use this full text search capability using the `search` argument\\.\n\n```graphql\nquery {\n products(search: \"ale\") {\n name\n }\n}\n\n```\n\n### Sorting\n\nTo sort or ordering results just use the `order_by` argument\\. This can be combined with `where`, `search`, etc to build complex queries to fit you needs.\n\n```graphql\nquery {\n products(order_by: { cached_votes_total: desc }) {\n id\n name\n }\n}\n\n```\n\n### Filtering\n\nSuper Graph support complex queries where you can add filters, ordering,offsets and limits on the query. For example the below query will list all products where the price is greater than 10 and the id is not 5.\n\n```graphql\nquery {\n products(where: { \n and: { \n price: { gt: 10 }, \n not: { id: { eq: 5 } } \n } \n }) {\n name\n price\n }\n}\n\n```\n\n#### Nested where clause targeting related tables\n\nSometimes you need to query a table based on a condition that applies to a related table. For example say you need to list all users who belong to an account. This query below will fetch the id and email or all users who belong to the account with id 3.\n\n```graphql\nquery {\n users(where: { \n accounts: { id: { eq: 3 } }\n }) {\n id\n email\n }\n}`\n\n```\n\n#### Logical Operators\n\n| Name | Example | Explained |\n|:--- |:--- |:--- |\n| and | price : \\{ and : \\{ gt: 10.5, lt: 20 \\} | price \\> 10.5 AND price < 20 |\n| or | or : \\{ price : \\{ greater\\_than : 20 \\}, quantity: \\{ gt : 0 \\} \\} | price \\>= 20 OR quantity \\> 0 |\n| not | not: \\{ or : \\{ quantity : \\{ eq: 0 \\}, price : \\{ eq: 0 \\} \\} \\} | NOT \\(quantity = 0 OR price = 0\\) |\n\n#### Other conditions\n\n| Name | Example | Explained |\n|:--- |:--- |:--- |\n| eq, equals | id : \\{ eq: 100 \\} | id = 100 |\n| neq, not\\_equals | id: \\{ not\\_equals: 100 \\} | id \\!= 100 |\n| gt, greater\\_than | id: \\{ gt: 100 \\} | id \\> 100 |\n| lt, lesser\\_than | id: \\{ gt: 100 \\} | id < 100 |\n| gte, greater\\_or\\_equals | id: \\{ gte: 100 \\} | id \\>= 100 |\n| lte, lesser\\_or\\_equals | id: \\{ lesser\\_or\\_equals: 100 \\} | id <= 100 |\n| in | status: \\{ in: \\[ \"A\", \"B\", \"C\" \\] \\} | status IN \\('A', 'B', 'C\\) |\n| nin, not\\_in | status: \\{ in: \\[ \"A\", \"B\", \"C\" \\] \\} | status IN \\('A', 'B', 'C\\) |\n| like | name: \\{ like \"phil%\" \\} | Names starting with 'phil' |\n| nlike, not\\_like | name: \\{ nlike \"v%m\" \\} | Not names starting with 'v' and ending with 'm' |\n| ilike | name: \\{ ilike \"%wOn\" \\} | Names ending with 'won' case\\-insensitive |\n| nilike, not\\_ilike | name: \\{ nilike \"%wOn\" \\} | Not names ending with 'won' case\\-insensitive |\n| similar | name: \\{ similar: \"%\\(b\\|d\\)%\" \\} | [Similar Docs](https://www.postgresql.org/docs/9/functions-matching.html#FUNCTIONS-SIMILARTO-REGEXP) |\n| nsimilar, not\\_similar | name: \\{ nsimilar: \"%\\(b\\|d\\)%\" \\} | [Not Similar Docs](https://www.postgresql.org/docs/9/functions-matching.html#FUNCTIONS-SIMILARTO-REGEXP) |\n| has\\_key | column: \\{ has\\_key: 'b' \\} | Does JSON column contain this key |\n| has\\_key\\_any | column: \\{ has\\_key\\_any: \\[ a, b \\] \\} | Does JSON column contain any of these keys |\n| has\\_key\\_all | column: \\[ a, b \\] | Does JSON column contain all of this keys |\n| contains | column: \\{ contains: \\[1, 2, 4\\] \\} | Is this array/json column a subset of value |\n| contained\\_in | column: \\{ contains: \"\\{'a':1, 'b':2\\}\" \\} | Is this array/json column a subset of these value |\n| is\\_null | column: \\{ is\\_null: true \\} | Is column value null or not |\n\n### Aggregations\n\nYou will often find the need to fetch aggregated values from the database such as `count`, `max`, `min`, etc. This is simple to do with GraphQL, just prefix the aggregation name to the field name that you want to aggregrate like `count_id`. The below query will group products by name and find the minimum price for each group. Notice the `min_price` field we're adding `min_` to price.\n\n```graphql\nquery {\n products {\n name\n min_price\n }\n}\n\n```\n\n| Name | Explained |\n|:--- |:--- |\n| avg | Average value |\n| count | Count the values |\n| max | Maximum value |\n| min | Minimum value |\n| stddev | [Standard Deviation](https://en.wikipedia.org/wiki/Standard_deviation) |\n| stddev\\_pop | Population Standard Deviation |\n| stddev\\_samp | Sample Standard Deviation |\n| variance | [Variance](https://en.wikipedia.org/wiki/Variance) |\n| var\\_pop | Population Standard Variance |\n| var\\_samp | Sample Standard variance |\n\nAll kinds of queries are possible with GraphQL. Below is an example that uses a lot of the features available. Comments `# hello` are also valid within queries.\n\n```graphql\nquery {\n products(\n # returns only 30 items\n limit: 30,\n\n # starts from item 10, commented out for now\n # offset: 10,\n\n # orders the response items by highest price\n order_by: { price: desc },\n\n # no duplicate prices returned\n distinct: [ price ]\n\n # only items with an id >= 30 and < 30 are returned\n where: { id: { and: { greater_or_equals: 20, lt: 28 } } }) {\n id\n name\n price\n }\n}\n\n```\n\nIn GraphQL mutations is the operation type for when you need to modify data. Super Graph supports the `insert`, `update`, `upsert` and `delete`. You can also do complex nested inserts and updates.\n\nWhen using mutations the data must be passed as variables since Super Graphs compiles the query into an prepared statement in the database for maximum speed. Prepared statements are are functions in your code when called they accept arguments and your variables are passed in as those arguments.\n\n### Insert\n\n```json\n{\n \"data\": { \n \"name\": \"Art of Computer Programming\",\n \"description\": \"The Art of Computer Programming (TAOCP) is a comprehensive monograph written by computer scientist Donald Knuth\",\n \"price\": 30.5\n }\n}\n\n```\n\n```graphql\nmutation {\n product(insert: $data) {\n id\n name\n }\n}\n\n```\n\n#### Bulk insert\n\n```json\n{\n \"data\": [{ \n \"name\": \"Art of Computer Programming\",\n \"description\": \"The Art of Computer Programming (TAOCP) is a comprehensive monograph written by computer scientist Donald Knuth\",\n \"price\": 30.5\n },\n { \n \"name\": \"Compilers: Principles, Techniques, and Tools\",\n \"description\": \"Known to professors, students, and developers worldwide as the 'Dragon Book' is available in a new edition\",\n \"price\": 93.74\n }]\n}\n\n```\n\n```graphql\nmutation {\n product(insert: $data) {\n id\n name\n }\n}\n\n```\n\n### Update\n\n```json\n{\n \"data\": { \n \"price\": 200.0\n },\n \"product_id\": 5\n}\n\n```\n\n```graphql\nmutation {\n product(update: $data, id: $product_id) {\n id\n name\n }\n}\n\n```\n\n#### Bulk update\n\n```json\n{\n \"data\": { \n \"price\": 500.0\n },\n \"gt_product_id\": 450.0,\n \"lt_product_id:\": 550.0\n}\n\n```\n\n```graphql\nmutation {\n product(update: $data, where: { \n price: { gt: $gt_product_id, lt: lt_product_id } \n }) {\n id\n name\n }\n}\n\n```\n\n### Delete\n\n```json\n{\n \"data\": { \n \"price\": 500.0\n },\n \"product_id\": 5\n}\n\n```\n\n```graphql\nmutation {\n product(delete: true, id: $product_id) {\n id\n name\n }\n}\n\n```\n\n#### Bulk delete\n\n```json\n{\n \"data\": { \n \"price\": 500.0\n }\n}\n\n```\n\n```graphql\nmutation {\n product(delete: true, where: { price: { eq: { 500.0 } } }) {\n id\n name\n }\n}\n\n```\n\n### Upsert\n\n```json\n{\n \"data\": { \n \"id\": 5,\n \"name\": \"Art of Computer Programming\",\n \"description\": \"The Art of Computer Programming (TAOCP) is a comprehensive monograph written by computer scientist Donald Knuth\",\n \"price\": 30.5\n }\n}\n\n```\n\n```graphql\nmutation {\n product(upsert: $data) {\n id\n name\n }\n}\n\n```\n\n#### Bulk upsert\n\n```json\n{\n \"data\": [{ \n \"id\": 5,\n \"name\": \"Art of Computer Programming\",\n \"description\": \"The Art of Computer Programming (TAOCP) is a comprehensive monograph written by computer scientist Donald Knuth\",\n \"price\": 30.5\n },\n { \n \"id\": 6,\n \"name\": \"Compilers: Principles, Techniques, and Tools\",\n \"description\": \"Known to professors, students, and developers worldwide as the 'Dragon Book' is available in a new edition\",\n \"price\": 93.74\n }]\n}\n\n```\n\n```graphql\nmutation {\n product(upsert: $data) {\n id\n name\n }\n}\n\n```\n\nOften you will need to create or update multiple related items at the same time. This can be done using nested mutations. For example you might need to create a product and assign it to a user, or create a user and his products at the same time. You just have to use simple json to define you mutation and Super Graph takes care of the rest.\n\n### Nested Insert\n\nCreate a product item first and then assign it to a user\n\n```json\n{\n \"data\": {\n \"name\": \"Apple\",\n \"price\": 1.25,\n \"created_at\": \"now\",\n \"updated_at\": \"now\",\n \"user\": {\n \"connect\": { \"id\": 5 }\n }\n }\n}\n\n```\n\n```graphql\nmutation {\n product(insert: $data) {\n id\n name\n user {\n id\n full_name\n email\n }\n }\n}\n\n```\n\nOr it's reverse, create the user first and then his product\n\n```json\n{\n \"data\": {\n \"email\": \"thedude@rug.com\",\n \"full_name\": \"The Dude\",\n \"created_at\": \"now\",\n \"updated_at\": \"now\",\n \"product\": {\n \"name\": \"Apple\",\n \"price\": 1.25,\n \"created_at\": \"now\",\n \"updated_at\": \"now\"\n }\n }\n}\n\n```\n\n```graphql\nmutation {\n user(insert: $data) {\n id\n full_name\n email\n product {\n id\n name\n price\n }\n }\n}\n\n```\n\n### Nested Update\n\nUpdate a product item first and then assign it to a user\n\n```json\n{\n \"data\": {\n \"name\": \"Apple\",\n \"price\": 1.25,\n \"user\": {\n \"connect\": { \"id\": 5 }\n }\n }\n}\n\n```\n\n```graphql\nmutation {\n product(update: $data, id: 5) {\n id\n name\n user {\n id\n full_name\n email\n }\n }\n}\n\n```\n\nOr it's reverse, update a user first and then his product\n\n```json\n{\n \"data\": {\n \"email\": \"newemail@me.com\",\n \"full_name\": \"The Dude\",\n \"product\": {\n \"name\": \"Banana\",\n \"price\": 1.25,\n }\n }\n}\n\n```\n\n```graphql\nmutation {\n user(update: $data, id: 1) {\n id\n full_name\n email\n product {\n id\n name\n price\n }\n }\n}\n\n```\n\n### Pagination\n\nThis is a must have feature of any API. When you want your users to go thought a list page by page or implement some fancy infinite scroll you're going to need pagination. There are two ways to paginate in Super Graph.\n\n Limit\\-Offset\nThis is simple enough but also inefficient when working with a large number of total items. Limit, limits the number of items fetched and offset is the point you want to fetch from. The below query will fetch 10 results at a time starting with the 100th item. You will have to keep updating offset \\(110, 120, 130, etc \\) to walk thought the results so make offset a variable.\n\n```graphql\nquery {\n products(limit: 10, offset: 100) {\n id\n slug\n name\n }\n}\n\n```\n\n#### Cursor\n\nThis is a powerful and highly efficient way to paginate though a large number of results. Infact it does not matter how many total results there are this will always be lighting fast. You can use a cursor to walk forward of backward though the results. If you plan to implement infinite scroll this is the option you should choose. \n\nWhen going this route the results will contain a cursor value this is an encrypted string that you don't have to worry about just pass this back in to the next API call and you'll received the next set of results. The cursor value is encrypted since its contents should only matter to Super Graph and not the client. Also since the primary key is used for this feature it's possible you might not want to leak it's value to clients. \n\nYou will need to set this config value to ensure the encrypted cursor data is secure. If not set a random value is used which will change with each deployment breaking older cursor values that clients might be using so best to set it.\n\n```yaml\n# Secret key for general encryption operations like \n# encrypting the cursor data\nsecret_key: supercalifajalistics\n\n```\n\nPaginating forward through your results\n\n```json\n{\n \"variables\": { \n \"cursor\": \"MJoTLbQF4l0GuoDsYmCrpjPeaaIlNpfm4uFU4PQ=\"\n }\n}\n\n```\n\n```graphql\nquery {\n products(first: 10, after: $cursor) {\n slug\n name\n }\n}\n\n```\n\nPaginating backward through your results\n\n```graphql\nquery {\n products(last: 10, before: $cursor) {\n slug\n name\n }\n}\n\n```\n\n```graphql\n\"data\": {\n \"products\": [\n {\n \"slug\": \"eius-nulla-et-8\",\n \"name\" \"Pale Ale\"\n },\n {\n \"slug\": \"sapiente-ut-alias-12\",\n \"name\" \"Brown Ale\"\n }\n ...\n ],\n \"products_cursor\": \"dJwHassm5+d82rGydH2xQnwNxJ1dcj4/cxkh5Cer\"\n}\n\n```\n\nNested tables can also have cursors. Requesting multiple cursors are supported on a single request but when paginating using a cursor only one table is currently supported. To explain this better, you can only use a `before` or `after` argument with a cursor value to paginate a single table in a query.\n\n```graphql\nquery {\n products(last: 10) {\n slug\n name\n customers(last: 5) {\n email\n full_name\n }\n }\n}\n\n```\n\nMultiple order\\-by arguments are supported. Super Graph is smart enough to allow cursor based pagination when you also need complex sort order like below.\n\n```graphql\nquery {\n products(\n last: 10\n before: $cursor\n order_by: [ price: desc, total_customers: asc ]) {\n slug\n name\n }\n}\n\n```\n\n\n## Using Variables\n\nVariables \\(`$product_id`\\) and their values \\(`\"product_id\": 5`\\) can be passed along side the GraphQL query. Using variables makes for better client side code as well as improved server side SQL query caching. The build\\-in web\\-ui also supports setting variables. Not having to manipulate your GraphQL query string to insert values into it makes for cleaner\nand better client side code.\n\n```javascript\n// Define the request object keeping the query and the variables seperate\nvar req = { \n query: '{ product(id: $product_id) { name } }' ,\n variables: { \"product_id\": 5 }\n}\n\n// Use the fetch api to make the query\nfetch('http://localhost:8080/api/v1/graphql', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(req),\n})\n.then(res => res.json())\n.then(res => console.log(res.data));\n\n```\n\n## GraphQL with React\n\nThis is a quick simple example using `graphql.js` [https://github.com/f/graphql.js/](https://github.com/f/graphql.js/)\n\n```js\nimport React, { useState, useEffect } from 'react'\nimport graphql from 'graphql.js'\n\n// Create a GraphQL client pointing to Super Graph\nvar graph = graphql(\"http://localhost:3000/api/v1/graphql\", { asJSON: true })\n\nconst App = () => {\n const [user, setUser] = useState(null)\n\n useEffect(() => {\n async function action() {\n // Use the GraphQL client to execute a graphQL query\n // The second argument to the client are the variables you need to pass\n const result = await graph(`{ user { id first_name last_name picture_url } }`)()\n setUser(result)\n }\n action()\n }, []);\n\n return (\n