1
3

More than 3 years have passed since last update.

Amplify × AppSyncでSubscriptionをフィルタリングする

Last updated at Posted at 2021-03-27

概要

リアルタイムデータの反映のためにsubscriptionを利用しています。@modelでsubscriptionを自動生成していましたが、自動生成ではフィルタリングができず、関係のないデータが一時的に表示されてしまう問題がありました。そこで、subscriptionを手動で作成し、引数でフィルタリングするようにしました。

実装

スキーマ

これまでは@modelでsubscriptionを自動生成していました。

type Task
@model(subscriptions: { level: public })
{
  id: ID!
  name: String!
  detail: String
}

↓生成

export const onCreateTask = /* GraphQL */ `
  subscription OnCreateTask {
    onCreateTask {
      id
      name
      detail
    }
  }
`;

export const onUpdateTask = /* GraphQL */ `
  subscription OnUpdateTask {
    onUpdateTask {
      id
      sequence
      name
      detail
    }
  }
`;

export const onDeleteTask = /* GraphQL */ `
  subscription OnDeleteTask {
    onDeleteTask {
      id
      name
      detail
    }
  }
`;

しかし、自動生成ではフィルタリングできません。
そのため、@modelでsubscriptionを自動生成しないように設定します。

type Task
@model(subscriptions: null)
{
  id: ID!
  name: String!
  detail: String
}

次に独自のsubscriptionをschema.graphqlに追加します。
Subscription名(引数): 型 @aws_subscribe(mutations: [Mutation名])のように書きます。

type Subscription {
  onCreateTaskByName(name: String): Task
    @aws_subscribe(mutations: ["createTask"])

  // Mutationのtypeはcreate・update・deleteの3種類。必要に応じて設定。
  onUpdateTaskByName(name: String): Task
    @aws_subscribe(mutations: ["updateTask"])
  onDeleteTaskByName(name: String): Task
    @aws_subscribe(mutations: ["deleteTask"])
}

↓生成

export const onCreateTaskByName = /* GraphQL */ `
  subscription OnCreateTaskByName($name: String) {
    onCreateTaskByName(name: $name) {
      id
      name
      detail
    }
  }
`;

export const onUpdateTaskByName = /* GraphQL */ `
  subscription OnUpdateTaskByName($name: String) {
    onUpdateTaskByName(name: $name) {
      id
      name
      detail
    }
  }
;`

export const onDeleteTaskByName = /* GraphQL */ `
  subscription OnDeleteTaskByName($name: String) {
    onDeleteTaskByName(name: $name) {
      id
      name
      detail
    }
  }
;'

これでsubscriptionに引数が渡せるようになり、フィルタリングをすることができるようになりました。

また、引数を複数設定することも可能です。引数を複数設定した場合はその引数に完全一致した場合のみsubscribeします。

type Subscription {
  onCreateTaskByName(name: String, detail: String): Task
    @aws_subscribe(mutations: ["createTask"])
}

呼び出し

import Amplify, { API } from "aws-amplify";
import { subscriptions } from "src/graphql/subscriptions";

function subscribe() {
    const subscription = API.graphql({
      query: subscriptions.onCreateTaskByName,
      variables: {
        name: "Test",
      },
    }).subscribe({
      next: ({ provider, value }) => {
        console.log("Subscribe:", { provider, value });
        subscription.unsubscribe();
      },
      error: (error) => console.warn(error),
    });
};

これで「Test」というnameのタスクを作成した時だけsubscribeできるようになりました。

graphqlOperationを利用する場合は下記のようにします。

import Amplify, { API, graphqlOperation } from "aws-amplify";
import { subscriptions } from "src/graphql/subscriptions";

function subscribe() {
    const subscription = API.graphql(
      // TypeScriptを利用している場合は型定義も可能
      graphqlOperation(subscriptions.onCreateTaskByName as 型, {
        name: "Test",
      })
    ).subscribe({
      next: ({ provider, value }) => {
        console.log("Subscribe:", { provider, value });
        subscription.unsubscribe();
      },
      error: (error) => console.warn(error),
    });
};

注意点

  • mockで動作しない

これでハマりました...
issueにmockで動作しないことが挙がっていました。closeされていますが、改修はされていないようです。そのため、毎回codgenを実行し、pushする必要があります。また、codegenでsubscriptionが自動生成されないことがありました。その場合は一度mockを起動すると生成可能です。
*2021/03 現在

issue:https://github.com/aws-amplify/amplify-cli/issues/6026

参考

(公式)
- Examples
- リアルタイムデータ
- Subscribe to data
(ブログ)
- AWS AppSync + Amplifyで、Subscriptionに引数を追加し、一部のみ通知を受け取ってみた



- Miyata Koki -
O:inc.でAmplify×React×React Nativeを使用して開発しています。大学のゼミでは統計学をPythonで行っています。
インターンやゼミで学んだ情報を発信していくので、フォロバするのでぜひこちらのアカウントのフォローお願いします!

1
3
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
3