【Prisma】該当する文字を含むアイテムを取得する

2025年6月24日

【Prisma】該当する文字を含むアイテムを取得する
export const searchPosts = async (search: string) => {
  const searchWords = search.trim().toLowerCase().split(/\s+/);

  return await prisma.post.findMany({
    where: {
      AND: searchWords.map(word => ({
        OR: [
          {
            title: {
              contains: word,
            },
          },
          {
            content: {
              contains: word,
            },
          },
        ],
      })),
    },
  });
};

この場合のANDORは、仮に2単語(searchWordsは長さ2の配列)だとして、titlecontentのどちらか(OR)で、map()でループされる単語1つ1つを(AND)含んでいなければならないという条件を表してます。

つまり、「毎ループ時、titlecontentどちらかでその文字を含んでね。」というニュアンスでしょう。

では以下の場合はどうなるのか。

export const searchPosts = async (search: string) => {
  const searchWords = search.trim().toLowerCase().split(/\s+/);

  return await prisma.post.findMany({
    where: {
      OR: searchWords.map(word => ({
        OR: [
          {
            title: {
              contains: word,
            },
          },
          {
            content: {
              contains: word,
            },
          },
        ],
      })),
    },
  });
};

これは毎ループ時という条件がなくなり、少なくとも1回、titlecontentで文字を含んでればいいよといった少し緩い条件になります。

具体例で見てみよう

例えば「React, 初心者」が検索ワードだとします。配列にすると、["React", "初心者"]

また、仮データも用意します。

// データ例
const posts = [
  { id: 1, title: "React入門", content: "初心者向けTypeScript解説" },
  { id: 2, title: "Vue.js入門", content: "Reactより簡単でおすすめ" },
  { id: 3, title: "TypeScript基礎", content: "型安全なJavaScript" },
  { id: 4, title: "React初心者ガイド", content: "基本的な使い方を解説" },
];

// 検索ワードの配列
const searchWords = ["React", "初心者"];

パターン1: AND検索の場合

一番最初に述べたパターンの場合です。

prisma.post.findMany({
    where: {
      AND: searchWords.map(word => ({
        OR: [
          {
            title: {
              contains: word,
            },
          },
          {
            content: {
              contains: word,
            },
          },
        ],
      })),
    },
});

この場合where句で該当するものは、
「毎ループ時、titlecontentどちらかでその文字を含んでね」という条件より、

  • "React"を、titleまたはcontentに含む
  • "初心者"を、titleまたはcontentに含む
    この両方を満たしているものということになります。

仮データの中でこの条件を満たしているのは以下になります。

  { id: 1, title: "React入門", content: "初心者向けTypeScript解説" }, 
  { id: 4, title: "React初心者ガイド", content: "基本的な使い方を解説" }

パターン2: OR検索の場合

2番目に述べたパターンの場合です。

prisma.post.findMany({
    where: {
      OR: searchWords.map(word => ({
        OR: [
          {
            title: {
              contains: word,
            },
          },
          {
            content: {
              contains: word,
            },
          },
        ],
      })),
    },
});

この場合where句で該当するものは、
「少なくとも1回、titlecontentどちらかでその文字を含んでね」という条件より、

  • "React"を、titleまたはcontentに含む
  • "初心者"を、titleまたはcontentに含む
    これらのどちらかを満たしているものになります。

仮データの中でこの条件を満たしているものは、以下になります。

  { id: 1, title: "React入門", content: "初心者向けTypeScript解説" },
  { id: 2, title: "Vue.js入門", content: "Reactより簡単でおすすめ" },
  { id: 4, title: "React初心者ガイド", content: "基本的な使い方を解説" }

タグ

コメント

シェア:

関連記事