LoginSignup
1
0

More than 5 years have passed since last update.

Azure FunctionsとGrapheneでCosmosDBデータ操作を行う(2)

Posted at

1. はじめに

Azure FunctionsとGrapheneでCosmosDBデータ操作を行う」ではAzure FunctionsでGraphQL APIのQueryオペレーションを実装していましたが、Mutationオペレーションを実装していなかったので、今回はMutationの実装を進めていきたいと思います。

前回までの事前準備や実施内容はこの記事この記事を参照ください。

2. GraphQLクエリのミューテーションの定義

Azure FunctionsとGrapheneでCosmosDBデータ操作を行う」で実施してきたことに引き続き、Grapheneを利用してGraphQLのMutationを実装していきます。実装についてはGraphene公式ドキュメントを参照していきます。

ミューテーションはデータソースに対する書き込みとその実行結果の取得を行う、GraphQLオペレーションになります。(クエリはデータソースに対する読み取り結果の取得のみ)

スキーマを定義し、次にリゾルバーを定義し、最後にリゾルバー内部にデータソースに対する処理を実装するという流れは前回同様ですが、リゾルバーの指定がQuery型で定義してきたものと若干異なります。

2.1. Mutationの各操作に対応するリゾルバー定義

GraphQLのMutation型の各操作(フィールド)とリゾルバー関数を対応づけるにあたり、操作毎にMutationを継承したクラスを用意しておきます。

#Mutation型の各操作と対応づけるリゾルバーの定義
class CreateItem(graphene.Mutation):
    class Arguments:
        item = ItemInput(required=True) #ミューテーションのAugument
    Output = Item #ミューテーションの実行結果の型
    def mutate(self, info, item): #Mutation実行時に呼び出される関数
        i = Itemオブジェクトを作成するDB操作
        return i

上記の例ではInput型のオブジェクトを利用しています。こちらはInputObjectTypeを継承したクラスを用意し、QueryやMutationの各操作にArgumentsとして渡せるようにします。

#idとmessageというフィールドを持つinput型の定義
class ItemInput(graphene.InputObjectType): #inputの定義
    id = graphene.String(required=True)
    message = graphene.String()

2.2. Mutation型の定義

GraphQLのMutation型もQuery型と同様にObjectTypeを継承したクラスとして用意します。
Mutation型ではフィールド名とMutationを継承したクラスを対応づけておくと、GraphQLクエリのミューテーションに記述されたフィールド名に対応するリゾルバーが呼び出されるという流れになります。(Mutation型とMutationを継承したクラスで紛らわしい...)

#createItemというフィールドを持つMutation型の定義
class Mutation(graphene.ObjectType):
    create_Item = CreateItem.Field()

なおsnake_caseはcamelCaseに置き換えてくれるとのこと

2.3. ルートクエリ宣言とミューテーションの実行

GraphQLのクエリを実行するにあたり、SchemaクラスでmutationとMutation型を対応づけ(ルートクエリ型の宣言)しておくことで、実際にミューテーションを実行(executeメソッドの呼び出し)する際に対応するMutationのリゾルバーの関数(というかクラスか)が呼び出されて処理が実行されるようになります。これはQuery型の場合と同様の動きになります。

schema = graphene.Schema(
    query=Query,
    mutation=Mutation #ここを追加
)
schema.execute("GraphQLのミューテーション")

2.4. GraphQL関連のコード

今回新たに追加したGraphQL関連のコードは以下になります。
#全体のコードはGitHubにはPUSHしていますが整理中です。

graphql/graphql.py
# input DBItemInput
class DBItemInput(graphene.InputObjectType):
    id = graphene.String(required=True)
    owner = graphene.String(required=True)
    partitionKey = graphene.ID(required=True)
    message = graphene.String()
    addition = graphene.String()

class CreateItem(graphene.Mutation):
    class Arguments:
        item = DBItemInput(required=True)
    Output = DbItem
    def mutate(self, info, item):
        results = DatabaseConnection().create_item(item).pop()
        i = DbItem.__new__(DbItem)
        i.__dict__.update(results)
        return i

class DeleteItem(graphene.Mutation):
    class Arguments:
        item = DBItemInput(required=True)
    Output = DbItem
    def mutate(self, info, item):
        results = DatabaseConnection().delete_item(item)
        if results.__len__() > 0:
            i = DbItem.__new__(DbItem)
            i.__dict__.update(results[0])
            return i
        return None

class UpsertItem(graphene.Mutation):
    class Arguments:
        item = DBItemInput(required=True)
    Output = DbItem
    def mutate(self, info, item):
        results = DatabaseConnection().upsert_item(item)
        i = DbItem.__new__(DbItem)
        i.__dict__.update(results) 
        return i

# type Mutation
class Mutation(graphene.ObjectType):
    create_Item = CreateItem.Field()
    delete_Item = DeleteItem.Field()
    upsert_Item = UpsertItem.Field()

class GraphQL:
    def __init__(self):
        self.schema = graphene.Schema(
            query=Query,
            mutation=Mutation
        )
        pass

    def query(self, query):
        results = self.schema.execute(query)
        return json.dumps(results.data)

上記のスキーマをGraphQLスキーマ定義言語で記述すると以下のような感じになります。

input DBItemInput {
  id: String!
  owner: String!
  partitionKey: String!
  message: String
  addition: String
}

type Mutation {
  createItem(DBItemInput!): DbItem
  deleteItem(DBItemInput!): DbItem
  upsertItem(DBItemInput!): DbItem
}

schema {
  query: Query
  mutation: Mutation
}

4. GraphQLミューテーションの実行確認

実装した関数にGraphQLのミューテーションを発行し、レスポンスを見たいと思います。実行方法については、
クエリの発行はcurlコマンドを使うほか、GraphiQLInsomniaを使う手があると思います。
 
curlコマンドの場合には以下でクエリを発行できます。

curl -X POST -H "Content-Type: application/json" -d '{"query": "mutation { createItem (item: {id: "id1", owner: "testuser", partitionKey: 1, message: "test message1", addition: "addtion message 1"}) { id message } }"}' http://localhost:7071/api/MyFunction

今回発行したGraphQLミューテーションは以下になります。Insomniaの場合はURLを指定し以下ミューテーションを発行するとレスポンスが得られます。

mutation {
  createItem(item: {id: "id1", owner: "testuser", partitionKey: 1, message: "test message1", addition: "addtion message 1"}) { 
    id
    message
  } 
}

Insomniaで確認すると以下のような結果になりました。
graphene-test03.png

GrahpQLの利用や実装を進めるにあたり、GraphQLの仕様や用語に関してもっと理解をしておきたいですね。

参考情報

Graphene
Graphene Mutation

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0