# Full-text search (/docs/orm/v6/prisma-client/queries/full-text-search)

Location: ORM > v6 > Prisma Client > Queries > Full-text search

Prisma Client supports full-text search for **PostgreSQL** databases in versions 2.30.0 and later, and **MySQL** databases in versions 3.8.0 and later. With full-text search (FTS) enabled, you can add search functionality to your application by searching for text within a database column.

> [!NOTE]
> In Prisma v6, FTS has been promoted to General Availability on MySQL. It still remains in Preview for PostgreSQL and requires using the `fullTextSearchPostgres` preview feature flag.

Enabling full-text search for PostgreSQL [#enabling-full-text-search-for-postgresql]

The full-text search API is currently a Preview feature. To enable this feature, carry out the following steps:

1. Update the [`previewFeatures`](/orm/v6/reference/preview-features) block in your schema to include the `fullTextSearchPostgres` preview feature flag:

   ```prisma title="schema.prisma" showLineNumbers
   generator client {
     provider        = "prisma-client"
     output          = "./generated"
     previewFeatures = ["fullTextSearchPostgres"]
   }
   ```

2. Generate Prisma Client:

   
     

#### npm

```bash
npx prisma generate
```

#### pnpm

```bash
pnpm dlx prisma generate
```

#### yarn

```bash
yarn dlx prisma generate
```

#### bun

```bash
bunx --bun prisma generate
```
   

After you regenerate your client, a new `search` field will be available on any `String` fields created on your models. For example, the following search will return all posts that contain the word 'cat'.

```ts
// All posts that contain the word 'cat'.
const result = await prisma.posts.findMany({
  where: {
    body: {
      search: "cat",
    },
  },
});
```

> **Note**: There currently is a [known issue](https://github.com/prisma/prisma/issues/23627) in the full-text search feature for PostgreSQL. If you observe slow search queries, you can [optimize your query with raw SQL](#full-text-search-with-raw-sql).

Querying the database [#querying-the-database]

The `search` field uses the database's native querying capabilities under the hood. This means that the exact query operators available are also database-specific.

PostgreSQL [#postgresql]

The following examples demonstrate the use of the PostgreSQL 'and' (`&`) and 'or' (`|`) operators:

```ts
// All posts that contain the words 'cat' or 'dog'.
const result = await prisma.posts.findMany({
  where: {
    body: {
      search: "cat | dog",
    },
  },
});

// All drafts that contain the words 'cat' and 'dog'.
const result = await prisma.posts.findMany({
  where: {
    status: "Draft",
    body: {
      search: "cat & dog",
    },
  },
});
```

To get a sense of how the query format works, consider the following text:

**"The quick brown fox jumps over the lazy dog"**

Here's how the following queries would match that text:

| Query         | Match? | Explanation                             |
| :------------ | :----- | :-------------------------------------- |
| `fox & dog`   | Yes    | The text contains 'fox' and 'dog'       |
| `dog & fox`   | Yes    | The text contains 'dog' and 'fox'       |
| `dog & cat`   | No     | The text contains 'dog' but not 'cat'   |
| `!cat`        | Yes    | 'cat' is not in the text                |
| `fox \| cat`  | Yes    | The text contains 'fox' or 'cat'        |
| `cat \| pig`  | No     | The text doesn't contain 'cat' or 'pig' |
| `fox <-> dog` | Yes    | 'dog' follows 'fox' in the text         |
| `dog <-> fox` | No     | 'fox' doesn't follow 'dog' in the text  |

For the full range of supported operations, see the [PostgreSQL full text search documentation](https://www.postgresql.org/docs/12/functions-textsearch.html).

MySQL [#mysql]

The following examples demonstrate use of the MySQL 'and' (`+`) and 'not' (`-`) operators:

```ts
// All posts that contain the words 'cat' or 'dog'.
const result = await prisma.posts.findMany({
  where: {
    body: {
      search: "cat dog",
    },
  },
});

// All posts that contain the words 'cat' and not 'dog'.
const result = await prisma.posts.findMany({
  where: {
    body: {
      search: "+cat -dog",
    },
  },
});

// All drafts that contain the words 'cat' and 'dog'.
const result = await prisma.posts.findMany({
  where: {
    status: "Draft",
    body: {
      search: "+cat +dog",
    },
  },
});
```

To get a sense of how the query format works, consider the following text:

**"The quick brown fox jumps over the lazy dog"**

Here's how the following queries would match that text:

| Query          | Match? | Description                                                   |
| :------------- | :----- | :------------------------------------------------------------ |
| `+fox +dog`    | Yes    | The text contains 'fox' and 'dog'                             |
| `+dog +fox`    | Yes    | The text contains 'dog' and 'fox'                             |
| `+dog -cat`    | Yes    | The text contains 'dog' but not 'cat'                         |
| `-cat`         | No     | The minus operator cannot be used on its own (see note below) |
| `fox dog`      | Yes    | The text contains 'fox' or 'dog'                              |
| `quic*`        | Yes    | The text contains a word starting with 'quic'                 |
| `quick fox @2` | Yes    | 'fox' starts within a 2 word distance of 'quick'              |
| `fox dog @2`   | No     | 'dog' does not start within a 2 word distance of 'fox'        |
| `"jumps over"` | Yes    | The text contains the whole phrase 'jumps over'               |

> **Note**: The - operator acts only to exclude rows that are otherwise matched by other search terms. Thus, a boolean-mode search that contains only terms preceded by - returns an empty result. It does not return “all rows except those containing any of the excluded terms.”

MySQL also has `>`, `<` and `~` operators for altering the ranking order of search results. As an example, consider the following two records:

**1. "The quick brown fox jumps over the lazy dog"**

**2. "The quick brown fox jumps over the lazy cat"**

| Query             | Result                   | Description                                                                                             |
| :---------------- | :----------------------- | :------------------------------------------------------------------------------------------------------ |
| `fox ~cat`        | Return 1. first, then 2. | Return all records containing 'fox', but rank records containing 'cat' lower                            |
| `fox (<cat >dog)` | Return 1. first, then 2. | Return all records containing 'fox', but rank records containing 'cat' lower than rows containing 'dog' |

For the full range of supported operations, see the [MySQL full text search documentation](https://dev.mysql.com/doc/refman/8.0/en/fulltext-boolean.html).

Sorting results by _relevance [#sorting-results-by-_relevance]

> [!WARNING]
> Sorting by relevance is only available for PostgreSQL and MySQL.

In addition to [Prisma Client's default `orderBy` behavior](/orm/v6/reference/prisma-client-reference#orderby), full-text search also adds sorting by relevance to a given string or strings. As an example, if you wanted to order posts by their relevance to the term `'database'` in their title, you could use the following:

```ts
const posts = await prisma.post.findMany({
  orderBy: {
    _relevance: {
      fields: ["title"],
      search: "database",
      sort: "asc",
    },
  },
});
```

Adding indexes [#adding-indexes]

PostgreSQL [#postgresql-1]

Prisma Client does not currently support using indexes to speed up full text search. There is an existing [GitHub Issue](https://github.com/prisma/prisma/issues/8950) for this.

MySQL [#mysql-1]

For MySQL, it is necessary to add indexes to any columns you search using the `@@fulltext` argument in the `schema.prisma` file.

In the following example, one full text index is added to the `content` field of the `Blog` model, and another is added to both the `content` and `title` fields together:

```prisma title="schema.prisma" showLineNumbers
generator client {
  provider        = "prisma-client"
  output          = "./generated"
}

model Blog {
  id      Int    @unique
  content String
  title   String

  @@fulltext([content])
  @@fulltext([content, title])
}
```

The first index allows searching the `content` field for occurrences of the word 'cat':

```ts
const result = await prisma.blogs.findMany({
  where: {
    content: {
      search: "cat",
    },
  },
});
```

The second index allows searching both the `content` and `title` fields for occurrences of the word 'cat' in the `content` and 'food' in the `title`:

```ts
const result = await prisma.blogs.findMany({
  where: {
    content: {
      search: "cat",
    },
    title: {
      search: "food",
    },
  },
});
```

However, if you try to search on `title` alone, the search will fail with the error "Cannot find a fulltext index to use for the search" and the message code is `P2030`, because the search requires an index on both fields.

Full-text search with raw SQL [#full-text-search-with-raw-sql]

Full-text search is currently in Preview, and due to a [known issue](https://github.com/prisma/prisma/issues/23627), you might experience slow search queries. If so, you can optimize your query using [TypedSQL](/orm/v6/prisma-client/using-raw-sql).

PostgreSQL [#postgresql-2]

With [TypedSQL](/orm/v6/prisma-client/using-raw-sql), you can use PostgreSQL's `to_tsvector` and `to_tsquery` to express your search query.

  

#### fullTextSearch.sql

```sql
SELECT * FROM "Blog" WHERE to_tsvector('english', "Blog"."content") @@ to_tsquery('english', ${term});
```

#### index.ts

```ts
import { fullTextSearch } from "@prisma/client/sql";

const term = `cat`;
const result = await prisma.$queryRawTyped(fullTextSearch(term));
```

> **Note**: Depending on your language preferences, you may exchange `english` against another language in the SQL statement.

If you want to include a wildcard in your search term, you can do this as follows:

  

#### fullTextSearch.sql

```sql
SELECT * FROM "Blog" WHERE to_tsvector('english', "Blog"."content") @@ to_tsquery('english', ${term});
```

#### index.ts

```ts
const term = `cat:*`; // [!code highlight]
const result = await prisma.$queryRawTyped(fullTextSearch(term));
```

MySQL [#mysql-2]

In MySQL, you can express your search query as follows:

  

#### fullTextSearch.sql

```sql
SELECT * FROM Blog WHERE MATCH(content) AGAINST(${term} IN NATURAL LANGUAGE MODE);
```

#### index.ts

```ts
const term = `cat`;
const result = await prisma.$queryRawTyped(fullTextSearch(term));
```

## Related pages

- [`Aggregation, grouping, and summarizing`](https://www.prisma.io/docs/orm/v6/prisma-client/queries/aggregation-grouping-summarizing): Use Prisma Client to aggregate, group by, count, and select distinct.
- [`Case sensitivity`](https://www.prisma.io/docs/orm/v6/prisma-client/queries/case-sensitivity): How Prisma Client handles case sensitivity when filtering and sorting.
- [`Computed fields`](https://www.prisma.io/docs/orm/v6/prisma-client/queries/computed-fields): This page explains how to use client extensions to add computed fields to Prisma models.
- [`CRUD`](https://www.prisma.io/docs/orm/v6/prisma-client/queries/crud): How to perform CRUD with Prisma Client.
- [`Custom models`](https://www.prisma.io/docs/orm/v6/prisma-client/queries/custom-models): This page explains how to wrap Prisma Client in custom models