Apollo+Expressで始めるGraphQL超入門 ~ データ取得Lv1

# あらすじ
[1.Apollo+Expressで始めるGraphQL超入門 ~ GraphQLをざっくり理解する](https://qiita.com/zonomaa/items/5de4b14dcd839db5f148)

# はじめに

前回の続きをやっていきます。
そのため使用するソースや環境構築は あらすじ を参照してくだい。

今回はデータの取得について色々書いていこうと思います。

※ 筆者はまだまだ初心者です。間違った解釈や実装などがあればご指摘お願いします。

# Select

GraphQLは、必要なときに必要なものを取得することできます。
いらないデータは指定しなければ取得されません。

```js
type User {
  id: Int
  name: String
  age: Int
  created_date: String
}
```

`User`に対して `id` と `name` があればOKであればクエリにそう書きましょう。

```graphql
{
  users {
    id
    name
  }
}

```

SQLのSELECTみたいな感じですね。

# Limit


## 実装

```diff:app.js
const typeDefs = gql`
  type User {
    id: Int
    name: String
    age: Int
    created_date: String
  }
  type Query {
-   users: [User]
+   users(limit: Int): [User]
  }
`;
```

`typeDefs` の `Query`の `users` に対して引数を設定します。
`limit` は数字がくるように設定しました。

```diff:app.js
const resolvers = {
  Query: {
-   users: () => users
+   users: (parent, args) => {
+     let result = users;
+     let limit = args.limit || null;
+
+     if (limit) {
+       result = result.slice(0, limit);
+     }
+
+     return result
+   }
  }
};
```

`resolvers` の `Query` に引数が渡るように設定しました。
`args` に引数が代入されます。
あとは、渡された `limit` の数字に沿って処理を行うだけです。

※ コードの書き足しを行ったらnodeタスクを再起動してください

## 実行

```graphql
{
  users(limit: 3) {
    id
    name
  }
}
```

<img width="1152" alt="スクリーンショット 2019-04-11 17.06.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211318/f7826ad0-7184-4ba9-fddc-03ae037ddb16.png">

Limit Done!

# Sort

`Users` を年齢でソートかけてみましょう。

年齢の降順、昇順が行えるように設定します。

## 実装

```diff:app.js
const typeDefs = gql`
  type User {
    id: Int
    name: String
    age: Int
    created_date: String
  }
  type Query {
    users: [User]
-   users(limit: Int): [User]
+   users(limit: Int, age_sort:String): [User]
  }
`;
```

`age_sort` という引数を足しました。 `String` 型で `DESC` か、 `ASC` が指定される想定です。

```diff:app.js
const resolvers = {
  Query: {
   users: () => users
   users: (parent, args) => {
     let result = users;
     let limit = args.limit || null;
+    let age_sort = args.age_sort || "";
+
+    if (age_sort) {
+      const ope = age_sort === 'ASC' ? 1 : -1;
+      result = users.sort((x, y) => {
+        if (x['age'] > y['age']) return ope;
+        if (x['age'] < y['age']) return -(ope);
+        return 0;
+      })
+    }

     if (limit) {
       result = result.slice(0, limit);
     }

     return result
   }
  }
};
```

これで年齢ソートができるようになります。

しかし、age_sortの引数に `DESC`, `ASC` 以外の文字列が設定されたらどうでしょう。
正しく処理が行えなくなってしまいます。

そこで新しい概念として `enum` を使ってみましょう。

enum とは TypeScriptで例えるとわかりやすいのですが


```typescript
age_sort: "DESC" | "ASC";
```

指定した文字列のみに制限することができます!

enumの場合だとこのような書き方となります。

```graphql
enum SortOP {
  ASC
  DESC
}
```

指定したい文字列が決まっている場合は `enum` を使ったほうが圧倒的にわかりやすくメンテしやすいコードになりますので、
こちらを使うことをおすすめします。

それでは `enum` で実装し直してみます。

```diff
const typeDefs = gql`
  type User {
    id: Int
    name: String
    age: Int
    created_date: String
  }
+ enum SortOP {
+   ASC
+   DESC
+ }
  type Query {
-   users(limit: Int, age_sort:String): [User]
+   users(limit: Int, age_sort:SortOP): [User]
  }
`;
```

これで `age_sort` には `ASC`, `DESC` が設定されるように型定義しました。


## 実行

```graphql
{
  users(age_sort: DESC) {
    name
    age
  }
}
```

<img width="1149" alt="スクリーンショット 2019-04-11 17.59.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211318/f69e1b40-1029-85b9-271e-b63df0674c92.png">


ソートすることができました。

# Sort & Limit

もちろん、SortとLimitを組み合わせて使うこともできます。

```graphql
{
  users(age_sort: DESC, limit: 2) {
    name
    age
  }
}
```

<img width="1150" alt="スクリーンショット 2019-04-11 18.00.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211318/5c58ca1f-a333-1550-ad77-0c8f1b098380.png">

# まとめ

簡単な取得系処理を実装してみました。
実際にやってみると、すごく自由度が高いという感想と、処理を足していくうちにどんどん肥大化していくんじゃないか？などいろいろと思うことがありました。
その部分を解消できる方法も調べてみたいと思います。

次回もう少し難易度を上げた [データ取得Lv2](https://qiita.com/zonomaa/items/eea698e7111da71d182b) に続きます！