LoginSignup
0
1

More than 1 year has passed since last update.

hasura graphqlで、「該当するレコードがテーブルになければレコードを追加する、あればレコードを更新する」がしたかった

Posted at

表題の通りです。結論としては、upsert mutationを使います。

前提

例えば、ブラウザ上で不特定の人数にアンケートを行う場合のテーブルの構造やクエリについて考えてみます。
テーブルには「回答のid(answerId)、回答(answer)、その解答をしたユーザー(userId)、その回答に対する質問番号(questionId)」の4つのカラムがあればよいです。

例) 回答テーブル

answerId answer userId questionId
1 ユーザーA 質問1
2 ユーザーB 質問1
3 ユーザーA 質問2
4 ユーザーC 質問3

さて、ユーザーが回答する際には、「まだ回答していない質問に答える(=DBに新しく回答を追加する)」ときと、「すでに回答したものを修正する(=DBに既に存在するレコードを更新する)」ときの2パターンがあります。クエリ的には、前者の場合はinsert mutationで、後者の場合はupdate mutationとなります。

insertupdateをいちいち切り替えるのは面倒だなと思いながらHasuraのドキュメントを読んでいたら、upsert mutationというものがありました。

詳しいqueryの記述例などは上記のリンクからドキュメントを読んでもらえればと思います。

ざっくりと説明しておくと、
insert用のクエリにon_conflictを追加します。そしてconstraintには「レコードが既にある」とみなすために参照するカラムがどれであるかを指定します。
レコードを追加する際にconstraintに指定されたカラムの値を参照し、同じ値を持っているレコードがあればそのレコードを更新する。なければ新しいレコードとして追加する、といった具合です。

  insert_answers(
    objects: { answerId: $answerId, answer: $answer, userId: $userId, questionId: $questionId }
    on_conflict: { constraint: answers_userId_questionId_key, update_columns: answer }
  ) 

ちなみに、constraintに指定するのはカラム名ではなく、ユニークキーとして設定されているカラムのキー名?です。

例えば以下の場合は、constraint: answerIdではなく、constraint: answers_pkeyと指定します。どんな名前が振られているかは、テーブルのModifyから確認することができます。
スクリーンショット 2023-03-30 14.51.07.png

先ほど例として挙げた回答テーブルでは、ユニークなキーは回答idとなっています。しかし、回答idはレコードがテーブルに追加されたときに生成されるものであるため、constraintに指定することはできません。
そのため、今回はユニークなキーとして、ユーザーidと質問idの複合キーを使いました。

テーブルのModifyのUnique Keysで、Add a new unique keysを選択し、ユーザーidと質問idを追加することで、ユニークな複合キーとしてキー名が生成されます。

スクリーンショット 2023-03-30 14.56.12.png

つまり今回の場合は、constraint: answers_userId_questionId_keyとしてクエリを実行すればよいです。

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