graphql-go/graphql を使ってGraphQLに入門する

新年初記事。

graphql-go/graphql

github.com

開発環境

> docker --version
Docker version 20.10.8, build 3967b7d

> docker-compose --version
docker-compose version 1.29.2, build 5becea4c

作ったもの

github.com

以下のようなクエリを投げると、

query := `
    {
        idols {
            id
            name
            age
            height
            birth_place
            birth_day
            blood_type
        }
    }
`

以下のようなレスポンスを出力する。

2022/01/23 06:08:34 {
        "data": {
                "idols": [
                        {
                                "age": 16,
                                "birth_day": "4/25",
                                "birth_place": "東京都",
                                "blood_type": "A",
                                "height": 155,
                                "id": 1,
                                "name": "櫻木 真乃"
                        },
                        {
                                "age": 16,
                                "birth_day": "7/22",
                                "birth_place": "アメリカ マサチューセッツ州",
                                "blood_type": "O",
                                "height": 157,
                                "id": 2,
                                "name": "八宮 めぐる"
                        },
                        ...
                        {
                                "age": 20,
                                "birth_day": "1/31",
                                "birth_place": "神奈川県",
                                "blood_type": "A",
                                "height": 161,
                                "id": 26,
                                "name": "斑鳩 ルカ"
                        }
                ]
        }
} 

クエリの引数の null 許容

クエリの引数の null 許容について、クエリの宣言時に意識する必要はなく、Resolver内で意識する必要がある。

例えば、以下のように使い分けたい時がある。

// age が20のフィールドのみを要求
{
    idols(age: 20) {
        id
        age
        name
    }
}

// 全件要求
{
    idols {
        id
        age
        name
    }
}

クエリの引数の null 許容を使い分けたい時は、Resolverの中で場合分けをすればいいだけでスッキリ書ける。

scheme, err := graphql.NewSchema(graphql.SchemaConfig{
    Query: graphql.NewObject(graphql.ObjectConfig{
        Name: "Query",
        Fields: graphql.Fields{
            "idols": &graphql.Field{
                Type: graphql.NewList(IdolType),
                Resolve: func(p graphql.ResolveParams) (interface{}, error) {
                    ageQuery, ok := p.Args["age"].(int)
                    var option = Option{}
                 
                    // null の時に false が入る
                    if ok {
                        option.age = ageQuery
                    }

                    res := getSameAgeIdols(db, option)
                    return res, nil;
                },
                Args: graphql.FieldConfigArgument{
                    "age": &graphql.ArgumentConfig{
                        Type: graphql.Int,
                    },
                },
            },
        },
    }),
})

まとめ

  • GraphQL、クエリ側でレスポンスの中身を柔軟に変更できるのが良い
  • 今回はコードでスキーマを表現するタイプのライブラリを使ったが、スキーマ駆動で進められるライブラリ(99designs/gqlgen)も試してみたくなった
  • 何か試す時は好きな題材でやるとモチベの維持が程よく出来てGood

参考