1
2

Prismaでリレーションされたレコードの有無を条件にデータ抽出したい場合の解決策

Posted at

Prismaとは

Prismaとは型安全なデータアクセスを提供するTypeScriptベースのORMです。
https://www.prisma.io/

やりたかったこと

以下のER図ようなテーブル構成があり、「タグAが紐づいている」、または 「全く紐づけがない」 アイテムを抽出する必要がありました。

1.png

「タグID Aが紐づいている」 という条件はsomeを使用することで実現できます。

where: {
    {
        tagsOnItems: {
            some: {
                tagId: 'A'
            }
        }
    },
}

しかし 「全く紐づけがない」 という条件が問題でした。
Prismaはオブジェクト型での条件式にexists句やsumの結果による判定を組み込むことができません。以下のようなリレーションにnullを指定する書式にも対応していません。

where: {
    {
        tagsOnItems: null
    },
}

解決策

Prismaにはネガティブなリレーション判定プロパティはnoneしか用意されていないので、noneを使用して以下のように 「紐づけ対象が存在しない」 という条件を構築しました。

where: {
    tagsOnItems: {
        none: {
            itemId: {
                not: ''
            }
         }
     }
}

Prismaでは条件の中にカレントアイテムのitemIdを明示的に指定することはできないので、itemIdで紐づいたtagsOnItemsに対してitemId: {not: ''} (*)とすることで、 「カレントアイテムのitemIdが設定されているレコード」 を絞り込むことができます。
その絞り込まれたレコードに対してnoneを指定することで 「カレントのアイテムIDを持つレコードが存在しない」=「紐づけ対象が存在しない」 という条件を実現しました。

※ itemIdはNOT NULLなので型制約によってitemId: {not: null}という条件が使用できません。そのため空文字を指定しています。

完成形

前述の各条件をORで内包することによって、「タグID Aが紐づいている」、または 「全く紐づけがない」 アイテムを抽出することができました。

where: {
    OR: [
        {
            tagsOnItems: {
                some: {
                    itemId: 'A'
                }
            }
        },
        {
            tagsOnItems: {
                none: {
                    itemId: {
                        not: ''
                    }
                }
            }
        }
    ]
}
1
2
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
2