こんにちは。KOUKIです。
GraphQLの実装の続きです。前回は、全てのBook情報を取得できるところまで実装しました。
今回は、クエリ操作を学んでいきましょう。
<目次>
記事まとめ
パラメータを渡す
現状だと、すべてのBookデータから情報を取得できますが、もう少し情報の絞り込みを行いたいと思います。
一意のBook情報を取得できるようにパラメータを渡せるようにしましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# app/api/schema.py import graphene from graphene_django.types import DjangoObjectType from .models import Book class BookType(DjangoObjectType): class Meta: model = Book class Query(graphene.ObjectType): all_books = graphene.List(BookType) # new book = graphene.Field(BookType, id=graphene.Int(), title=graphene.String()) def resolve_all_books(self, info, **kwargs): return Book.objects.all() # new def resolve_book(self, info, **kwargs): id = kwargs.get('id') title = kwargs.get('title') if id is not None: return Book.objects.get(pk=id) if title is not None: return Book.objects.get(title=title) return None |
一意のデータを取得するため、bookフィールドを設けました。
リクエストのパラメータはkwargsに入ってくる為、resolve_book関数にてデータの絞り込みを行っています。
それでは、「http://localhost:8080/graphql/」にアクセスして、次のクエリを実行してみましょう。
1 2 3 4 5 6 7 8 |
# query query { book(id: 1) { id title publish } } |
上記の通り、パラメータはサーバーサイドに実装したQueryのフィールド名にカッコ「()」をつけて指定します。
このクエリを実行すると次の結果が取得できます。
1 2 3 4 5 6 7 8 9 |
{ "data": { "book": { "id": "1", "title": "Harry Potter and the Philosopher's Stone", "publish": 1997 } } } |
カスタムクエリフィールド
基本的にクエリに指定できるフィールドは、Django Modelに設定したフィールドになりますが、自分でカスタマイズしたフィールドに対してクエリを実行することもできます。
BookTypeに次のフィールドを追加します。
1 2 3 4 5 6 7 8 9 10 |
# app/api/schema.py class BookType(DjangoObjectType): class Meta: model = Book book_new = graphene.String() def resolve_book_new(self, info): return "Old Book" if self.publish < 1999 else "New Book" |
ブラウザをリロードして、次のクエリを実行してみましょう。
1 2 3 4 5 6 7 8 |
query { allBooks { id title publish bookNew } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
{ "data": { "allBooks": [ { "id": "1", "title": "Harry Potter and the Philosopher's Stone", "publish": 1997, "bookNew": "Old Book" }, { "id": "2", "title": "Harry Potter and the Chamber of Secrets", "publish": 1998, "bookNew": "Old Book" }, { "id": "3", "title": "Harry Potter and the Prisoner of Azkaban", "publish": 1999, "bookNew": "New Book" }, { "id": "4", "title": "Harry Potter and the Goblet of Fire", "publish": 2000, "bookNew": "New Book" } ] } } |
bookNewフィールドが新たに取得できましたね。
関連フィールドの検索
Bookモデルには、Authorモデルが紐づいています。
1 2 3 4 5 6 7 |
class Book(models.Model): title = models.CharField(max_length=255) publish = models.IntegerField(default=2000) author = models.ForeignKey(Author, # ★ on_delete=models.PROTECT, blank=True, null=True) |
authorフィールドは、現状取得することができないため、この情報を取得できるようにしましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# app/api/schema.py import graphene from graphene_django.types import DjangoObjectType from .models import Author, Book class BookType(DjangoObjectType): class Meta: model = Book book_new = graphene.String() def resolve_book_new(self, info): return "Old Book" if self.publish < 1999 else "New Book" # new class AuthorType(DjangoObjectType): class Meta: model = Author class Query(graphene.ObjectType): all_books = graphene.List(BookType) book = graphene.Field(BookType, id=graphene.Int(), title=graphene.String()) # new all_authors = graphene.List(AuthorType) # new def resolve_all_authors(self, info, **kwargs): return Author.objects.all() def resolve_all_books(self, info, **kwargs): return Book.objects.all() def resolve_book(self, info, **kwargs): id = kwargs.get('id') title = kwargs.get('title') if id is not None: return Book.objects.get(pk=id) if title is not None: return Book.objects.get(title=title) return None |
ブラウザをリロードして、次のクエリを実行してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 |
query { book(id: 1) { id title publish author { id firstname lastname } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{ "data": { "book": { "id": "1", "title": "Harry Potter and the Philosopher's Stone", "publish": 1997, "author": { "id": "1", "firstname": "Joanne", "lastname": "Rowling" } } } } |
すごく便利ですね^^
Aliaseを付ける
クエリにはAliaseを付けて、実行することができます。
下記の例では、firstbookとsecondbookがAliaseです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
query { firstbook: book(id: 1) { id title publish author { id firstname lastname } }, secondbook: book(id: 2) { id title publish author { id firstname lastname } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
{ "data": { "firstbook": { "id": "1", "title": "Harry Potter and the Philosopher's Stone", "publish": 1997, "author": { "id": "1", "firstname": "Joanne", "lastname": "Rowling" } }, "secondbook": { "id": "2", "title": "Harry Potter and the Chamber of Secrets", "publish": 1998, "author": { "id": "1", "firstname": "Joanne", "lastname": "Rowling" } } } } |
Fragmentを付ける
先ほどのクエリは同じフィールド名を指定していて、少し冗長ですよね?
GraphQLでは、Fragmentで記述を簡略化できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
query { firstbook: book(id: 1) { ...bookData } secondbook: book(id: 2) { ...bookData } } fragment bookData on BookType { id title publish author { id firstname lastname } } |
fragmentキーワードと共に共通化したいクエリを括りだしています。
これらのフィールドは、BookTypeに紐づくものであるため、on XXXXで明確に指定しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
{ "data": { "firstbook": { "id": "1", "title": "Harry Potter and the Philosopher's Stone", "publish": 1997, "author": { "id": "1", "firstname": "Joanne", "lastname": "Rowling" } }, "secondbook": { "id": "2", "title": "Harry Potter and the Chamber of Secrets", "publish": 1998, "author": { "id": "1", "firstname": "Joanne", "lastname": "Rowling" } } } } |
変数の利用
GraphQLは、変数を用いることができます。
変数を表すためには、文字列の先頭に$マークを付けて宣言する必要があります。
下記の例で言うと$idが変数名です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
query getBook($id: Int){ book(id: $id) { ...bookData } } fragment bookData on BookType { id title publish author { id firstname lastname } } |
ブラウザ上のGraphiQLに「QUERY VARIABLES」項目があると思いますので、そこに変数の値を設定してください。

1 2 3 |
{ "id": 1 } |
クエリを実行してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{ "data": { "book": { "id": "1", "title": "Harry Potter and the Philosopher's Stone", "publish": 1997, "author": { "id": "1", "firstname": "Joanne", "lastname": "Rowling" } } } } |
これで、処理の中でも利用しやすくなりましたね。
条件分岐
GraphQLでは、条件分岐にも対応しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
query getBook($id: Int, $live: Boolean = false){ book(id: $id) { ...bookData } } fragment bookData on BookType { id title publish author @include(if: $live){ id firstname lastname } } |
「QUERY VARIABLES」には、次の値を設定します。
1 2 3 4 |
{ "id": 1, "live": true } |
以下、出力結果です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# Falseの場合 { "data": { "book": { "id": "1", "title": "Harry Potter and the Philosopher's Stone", "publish": 1997 } } } #Trueの場合 { "data": { "book": { "id": "1", "title": "Harry Potter and the Philosopher's Stone", "publish": 1997, "author": { "id": "1", "firstname": "Joanne", "lastname": "Rowling" } } } } |
次回
次回は、Mutationを学びましょう。
コメントを残す
コメントを投稿するにはログインしてください。