GraphQL メモ

## 始め方

このチュートリアルが非常にわかりやすかったので、そのメモ。

https://learngraphql.com/basics/introduction

サンドボックス環境を公開してくれてる。
GraphQL のコンソールで試すのが一番よい。

https://sandbox.learngraphql.com/

qiita で graphql のハイライト対応してほしい。
もしくは、なんかうまいこと似た構文のもの無いだろうか。

## query

サーバ側で type を定義する

```js
const Post = new GraphQLObjectType({
  name: "Post",
  fields: () => ({
    _id: {type: new GraphQLNonNull(GraphQLString)},
    title: {type: new GraphQLNonNull(GraphQLString)},
    content: {type: GraphQLString}
  })
});
```

この type に対する query を定義する


```js
const Query = new GraphQLObjectType({
  name: 'BlogSchema',
  fields: () => ({
    posts: {
      type: new GraphQLList(Post),
      resolve: () => PostsList // これがデータ
    }
  })
});

```

schema に登録

```js
const Schema = new GraphQLSchema({
  query: Query
});
```

取得

```
{
  posts
}
```

これを補完すれば、こうなる。

```
{
  posts {
    _id
    content
  }
}
```

結果

```
 "data": {
   "posts": [
     {
       "_id": "0176413761b289e6d64c2c14a758c1c7",
       "content": "Most developers and companies..",
     },
     {
       "_id": "03390abb5570ce03ae524397d215713b",
       "content": "Here is a common feedback...",
     },
     {
       "_id": "0be4bea0330ccb5ecf781a9f69a64bc8",
       "content": "<script type=\"text/javasc...",
     }
   ]
}
```

属性は、横並びでも良い。カンマは無くても良い。


## nest

Post に Author をひもづける

type 定義

```js
const Author = new GraphQLObjectType({
  name: "Author",
  fields: () => ({
    _id: {type: new GraphQLNonNull(GraphQLString)},
    name: {type: GraphQLString}
  })
});
```

紐づけ

```js
const Post = new GraphQLObjectType({
  name: "Post",
  fields: () => ({
    ...
    author: {
      type: Author,
      resolve: post => AuthorsList.find(a => a._id == post.author);
    }
  })
});
```


とれる

```
{
  posts {
    _id
  }

  authors {
    _id
  }
}
```

同じリソースの結果を別の塊でとりたい場合は、名前をつける。

```
{
  names: authors {
    name
  },

  ids: authors {
    _id
  }
}
```

## fragment

共通部の切り出しと埋め込み

```
{
  post1: post(_id: "03390abb5570ce03ae524397d215713b") {
    ...postInfo
  },
  post2: post(_id: "0176413761b289e6d64c2c14a758c1c7") {
    ...postInfo
  }
}

fragment postInfo on Post {
  title,
  content,
  ...authorInfo
  comments {
    content,
    ...authorInfo
  }
}

fragment authorInfo on HasAuthor {
  author {
    _id,
    name
  }
}
```

## 引数あり

これも query と呼ばれてる。
パラメータを引数にとる。


```js
const Query = new GraphQLObjectType({
  name: 'BlogSchema',
  fields: () => ({
    posts: {
      ...
    },

    recentPosts: {
      type: new GraphQLList(Post),
      args: {
        count: {
          type: new GraphQLNonNull(GraphQLInt),
        }
      },
      resolve: function(source, {count}) {
        PostsList.sort((a, b) => {
          var bTime = new Date(b.date['$date']).getTime();
          var aTime = new Date(a.date['$date']).getTime();

          return bTime - aTime;
        });

        return PostsList.slice(0, count)
      }
    },
  })
});
```

これを叩く。 (author には comments がある前提)

```
{
  recentPosts(count: 2) {
    title,
    comments(limit: 1) {
      content
    }
  }
}
```

この引数を動的に指定したい場合。


```js
query getFewPosts($postCount: Int!, $commentCount: Int) {
  recentPosts(count: $postCount) {
    title,
    ...comments
  }
}

fragment comments on Post {
  comments(limit: $commentCount) {
    content
  }
}
```

query variable はこう



```
{
  "postCount": 3,
  "commentCount": 2,
}
```


## mutation

`関数名(引数) {戻り値}` みたな感じ。

type 定義のようなもの

```js
mutation insertFirstPost {
  post: createPost(
    title: "GraphQL is Awesome",
    content: "Yep, it's purely awesome."
  ) {
    _id,
    title
  }
}
```

query 定義のようなもの

```js
const Mutation = new GraphQLObjectType({
  name: "BlogMutations",
  fields: () => ({
    createPost: {
      // 戻り型
      type: Post,
      // 引数
      args: {
        title: {type: new GraphQLNonNull(GraphQLString)},
        content: {type: new GraphQLNonNull(GraphQLString)}
      },
      // ロジック
      resolve: (source, args) => {
        let post = _.clone(args);
        post._id = Date.now() + Math.ceil(Math.random() * 9999999);
        post.author = "arunoda";
        PostsList.push(post);
        return post;
      }
    }
  })
});
```

schema に登録

```js
const Schema = new GraphQLSchema({
  query: Query,
  mutation: Mutation
});
```


更新に使う
やっぱり `関数名(引数) {戻り値}` みたな感じ。

```
mutation {
  createAuthor(
    _id: "jxck",
    name: "Jxck",
    twitterHandle: "@jxck"
  ) {
    _id
    name
  }
}
```

複数

```
mutation {
  sam: createAuthor(
    _id: "sam",
    name: "Sam Hautom"
    twitterHandle: "@sam"
  ) {
    _id
    name
  },

  chris: createAuthor(
    _id: "chris",
    name: "Chris Mather"
    twitterHandle: "@chris"
  ) {
    _id
    name
  }
}
```

ちょっと慣れてきた。