🦔

Prismaで多対多の検索

2023/11/12に公開

昔理解できてなかった時にちょっとハマったのでメモ。


よくある構成です。

Article

id title content
1 タイトル1 ...
2 タイトル2 ...
3 タイトル3 ...
4 タイトル4 ...

Category

id name
1 カテゴリ1
2 カテゴリ2
3 カテゴリ3

ArticleOnCategory

articleId categoryId
1 1
1 2
1 3
2 1
3 3
4 1
4 2

カテゴリ1とカテゴリ2の両方に属する記事の抽出

ダメな例

await prisma.article.findMany({
  where: {
    ArticleOnCategory: {
      every: {
        categoryId: {
          in: [1, 2]
        }
      }
    }
  }
})

正しい方法

await prisma.article.findMany({
  where: {
    AND: [
      {ArticleOnCategory: {some: {categoryId: 1}}},
      {ArticleOnCategory: {some: {categoryId: 2}}}
    ]
  }
})

配列から組み立てる

const categoryIds = [1, 2]

await prisma.article.findMany({
  where: {
    AND: categoryIds.map(categoryId => {
      return {ArticleOnCategory: {some: {categoryId}}}
    })
  }
})

カテゴリ1とカテゴリ2のいずれかに属する記事の抽出

ORの場合はどっちでもOK。

await prisma.article.findMany({
  where: {
    ArticleOnCategory: {
      some: {
        categoryId: {
          in: [1, 2]
        }
      }
    }
  }
})
await prisma.article.findMany({
  where: {
    OR: [
      {ArticleOnCategory: {some: {categoryId: 1}}},
      {ArticleOnCategory: {some: {categoryId: 2}}}
    ]
  }
})

Discussion