|
| 1 | +## Feature Example - Prisma Full-Text Search (PostgreSQL) |
| 2 | + |
| 3 | +This project demonstrates how to use [Prisma's Full-Text Search](https://www.prisma.io/docs/v6/orm/prisma-client/queries/full-text-search) on PostgreSQL with Keystone, using `extendPrismaSchema` to enable the `fullTextSearchPostgres` preview feature and a custom GraphQL query to expose it. |
| 4 | + |
| 5 | +> **Note:** This example requires a running PostgreSQL database. Full-text search is not available on SQLite. |
| 6 | +
|
| 7 | +## Instructions |
| 8 | + |
| 9 | +To run this project, clone the Keystone repository locally then run `pnpm install` at the root of the repository. |
| 10 | + |
| 11 | +Set your database URL: |
| 12 | + |
| 13 | +```shell |
| 14 | +export DATABASE_URL="postgresql://localhost/keystone-example" |
| 15 | +``` |
| 16 | + |
| 17 | +Then navigate to this directory and run: |
| 18 | + |
| 19 | +```shell |
| 20 | +pnpm dev |
| 21 | +``` |
| 22 | + |
| 23 | +This will start the Admin UI at [localhost:3000](http://localhost:3000). |
| 24 | +You can use the Admin UI to create items in your database. |
| 25 | + |
| 26 | +You can also access a GraphQL Playground at [localhost:3000/api/graphql](http://localhost:3000/api/graphql), which allows you to directly run GraphQL queries and mutations. |
| 27 | + |
| 28 | +## Features |
| 29 | + |
| 30 | +### Enabling Full-Text Search with `extendPrismaSchema` |
| 31 | + |
| 32 | +Prisma's `fullTextSearchPostgres` is a [preview feature](https://www.prisma.io/docs/v6/orm/reference/preview-features/client-preview-features) that must be explicitly enabled in the Prisma generator block. Since Keystone manages the `schema.prisma` file automatically, you can inject this using `extendPrismaSchema` in your Keystone config: |
| 33 | + |
| 34 | +```typescript |
| 35 | +db: { |
| 36 | + provider: 'postgresql', |
| 37 | + extendPrismaSchema: schema => { |
| 38 | + return schema.replace( |
| 39 | + /(generator [^}]+)}/g, |
| 40 | + ['$1', ' previewFeatures = ["fullTextSearchPostgres"]', '}'].join('\n') |
| 41 | + ) |
| 42 | + }, |
| 43 | +} |
| 44 | +``` |
| 45 | + |
| 46 | +This produces a generator block like: |
| 47 | + |
| 48 | +```prisma |
| 49 | +generator client { |
| 50 | + provider = "prisma-client-js" |
| 51 | + previewFeatures = ["fullTextSearchPostgres"] |
| 52 | +} |
| 53 | +``` |
| 54 | + |
| 55 | +### Custom `searchPosts` Query |
| 56 | + |
| 57 | +Prisma's `search` operator is a low-level Prisma feature not yet surfaced through Keystone's `context.db` query layer. To use it, the example reaches for the raw Prisma client via `context.prisma`, then converts the results back to Keystone-typed objects using `context.db`: |
| 58 | + |
| 59 | +```typescript |
| 60 | +// 1. Use raw Prisma client to perform the full-text search |
| 61 | +const matches = await context.prisma.post.findMany({ |
| 62 | + where: { |
| 63 | + OR: [{ title: { search: query } }, { content: { search: query } }], |
| 64 | + }, |
| 65 | + select: { id: true }, |
| 66 | +}) |
| 67 | + |
| 68 | +// 2. Fetch proper Keystone Post objects using the matched IDs |
| 69 | +const ids = matches.map(p => p.id) |
| 70 | +return context.db.Post.findMany({ where: { id: { in: ids } } }) |
| 71 | +``` |
| 72 | + |
| 73 | +### PostgreSQL Full-Text Search Syntax |
| 74 | + |
| 75 | +The `query` argument accepts PostgreSQL's tsquery syntax: |
| 76 | + |
| 77 | +| Operator | Meaning | Example | |
| 78 | +| -------- | ---------------- | ------------------------------------------------------- | |
| 79 | +| `&` | AND | `"cat & dog"` — must contain both | |
| 80 | +| `\|` | OR | `"cat \| dog"` — must contain either | |
| 81 | +| `!` | NOT | `"!cat"` — must not contain | |
| 82 | +| `<->` | Phrase/proximity | `"fox <-> dog"` — "dog" follows immediately after "fox" | |
| 83 | + |
| 84 | +### Try it in the GraphQL Playground |
| 85 | + |
| 86 | +After creating some posts in the Admin UI, open [localhost:3000/api/graphql](http://localhost:3000/api/graphql) and run: |
| 87 | + |
| 88 | +```graphql |
| 89 | +query { |
| 90 | + searchPosts(query: "keystone & graphql") { |
| 91 | + id |
| 92 | + title |
| 93 | + content |
| 94 | + author { |
| 95 | + name |
| 96 | + } |
| 97 | + } |
| 98 | +} |
| 99 | +``` |
| 100 | + |
| 101 | +## Try it out in CodeSandbox 🧪 |
| 102 | + |
| 103 | +You can play with this example online in a web browser using the free [codesandbox.io](https://codesandbox.io/) service. To launch this example, open the URL <https://githubbox.com/keystonejs/keystone/tree/main/examples/extend-full-text-search>. You can also fork this sandbox to make your own changes. |
0 commit comments