全文搜索
Prisma 客户端在 2.30.0 及更高版本的 PostgreSQL 数据库和 3.8.0 及更高版本的 MySQL 数据库中支持全文搜索。启用全文搜索后,你可以通过在数据库列中搜索文本,为你的应用程序添加搜索功能。
注意:全文搜索功能目前存在一个 已知问题。如果你观察到搜索查询缓慢,你可以 使用原始 SQL 优化你的查询。
启用全文搜索
全文搜索 API 目前是一个预览功能。要启用此功能,请执行以下步骤
-
更新你的模式中的
previewFeatures
块以包含fullTextSearch
预览功能标志schema.prismagenerator client {
provider = "prisma-client-js"
previewFeatures = ["fullTextSearch"]
}对于 MySQL,你还需要包含
fullTextIndex
预览功能标志schema.prismagenerator client {
provider = "prisma-client-js"
previewFeatures = ["fullTextSearch", "fullTextIndex"]
} -
生成 Prisma 客户端
npx prisma generate
在重新生成客户端后,在模型上创建的任何 String
字段上都会出现一个新的 search
字段。例如,以下搜索将返回所有包含“cat”一词的帖子。
// All posts that contain the word 'cat'.
const result = await prisma.posts.findMany({
where: {
body: {
search: 'cat',
},
},
})
查询数据库
search
字段在幕后使用数据库的本机查询功能。这意味着可用的确切查询运算符也是特定于数据库的。
PostgreSQL
以下示例演示了 PostgreSQL 'and' (&
) 和 'or' (|
) 运算符的使用
// 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',
},
},
})
为了了解查询格式的工作原理,请考虑以下文本
"The quick brown fox jumps over the lazy dog"
以下是以下查询匹配该文本的方式
查询 | 匹配? | 描述 |
---|---|---|
fox & dog | 是 | 文本包含“fox”和“dog”。 |
dog & fox | 是 | 是 |
文本包含“dog”和“fox”。 | dog & cat | 否 |
文本包含“dog”但不包含“cat”。 | 是 | !cat |
文本中没有“cat”。 | 是 | fox | cat |
是 | dog & cat | 文本包含“fox”或“cat”。 |
cat | pig | 是 | 否 |
文本不包含“cat”或“pig”。 | dog & cat | fox <-> dog |
是
文本中“dog”紧随“fox”之后。
dog <-> fox
// 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',
},
},
})
为了了解查询格式的工作原理,请考虑以下文本
"The quick brown fox jumps over the lazy dog"
以下是以下查询匹配该文本的方式
查询 | 匹配? | 描述 |
---|---|---|
否 | 是 | 文本包含“fox”和“dog”。 |
文本中“fox”不紧随“dog”之后。 | 是 | 是 |
有关支持操作的完整范围,请参阅 PostgreSQL 全文搜索文档。 | 是 | 否 |
MySQL | dog & cat | 以下示例演示了 MySQL 'and' (+ ) 和 'not' (- ) 运算符的使用 |
+fox +dog | 是 | +dog +fox |
+dog -cat | 是 | -cat |
减号运算符不能单独使用(参见下面的说明) | 是 | fox dog |
是 | dog & cat | 文本包含“fox”或“dog”。 |
quic* | 是 | 是 |
文本包含以“quic”开头的单词。
quick fox @2
是
“fox”的起始位置与“quick”的距离不超过 2 个单词。
查询 | fox dog @2 | 描述 |
---|---|---|
否 | “dog”的起始位置与“fox”的距离超过 2 个单词。 | "jumps over" |
是 | “dog”的起始位置与“fox”的距离超过 2 个单词。 | 文本包含整个短语“jumps over”。 |
注意:减号运算符仅用于排除其他搜索词匹配的行。因此,布尔模式搜索如果只包含以减号开头的词,则返回空结果。它不返回“除了包含任何排除词的行以外的所有行”。
MySQL 还具有 >
、<
和 ~
运算符,用于更改搜索结果的排名顺序。例如,请考虑以下两条记录
2. "The quick brown fox jumps over the lazy cat"
结果
const posts = await prisma.post.findMany({
orderBy: {
_relevance: {
fields: ['title'],
search: 'database',
sort: 'asc'
},
},
})
fox ~cat
1. 首先返回,然后是 2.
返回所有包含“fox”的记录,但将包含“cat”的记录的排名降低
fox (<cat >dog)
返回所有包含“fox”的记录,但将包含“cat”的记录的排名降低,低于包含“dog”的行。
有关支持操作的完整范围,请参阅 MySQL 全文搜索文档。
generator client {
provider = "prisma-client-js"
previewFeatures = ["fullTextSearch", "fullTextIndex"]
}
model Blog {
id Int @unique
content String
title String
@@fulltext([content])
@@fulltext([content, title])
}
按 _relevance
排序结果
const result = await prisma.blogs.findMany({
where: {
content: {
search: 'cat',
},
},
})
警告
const result = await prisma.blogs.findMany({
where: {
content: {
search: 'cat',
},
title: {
search: 'food',
},
},
})
仅 PostgreSQL 和 MySQL 支持按相关性排序。
除了 Prisma 客户端的默认 orderBy
行为 外,全文搜索还添加了按给定字符串或字符串的相关性排序。例如,如果你想按帖子的标题与术语 'database'
的相关性对其进行排序,你可以使用以下方法
添加索引
PostgreSQL
Prisma 客户端目前不支持使用索引来加速全文搜索。有一个关于此的现有 GitHub 问题。
- MySQL
- 对于 MySQL,需要在使用
schema.prisma
文件中的@@fulltext
参数搜索的任何列中添加索引。为此,必须启用"fullTextIndex"
预览功能。
SELECT * FROM "Blog" WHERE to_tsvector('english', "Blog"."content") @@ to_tsquery('english', ${term});
import { fullTextSearch } from "@prisma/client/sql"
const term = `cat`
const result = await prisma.$queryRawTyped(fullTextSearch(term))
在以下示例中,一个全文索引被添加到
Blog
模型的content
字段,另一个被添加到content
和title
字段。
第一个索引允许在 content
字段中搜索“cat”一词的出现情况。
- MySQL
- 对于 MySQL,需要在使用
schema.prisma
文件中的@@fulltext
参数搜索的任何列中添加索引。为此,必须启用"fullTextIndex"
预览功能。
SELECT * FROM "Blog" WHERE to_tsvector('english', "Blog"."content") @@ to_tsquery('english', ${term});
const term = `cat:*`
const result = await prisma.$queryRawTyped(fullTextSearch(term))
第二个索引允许在 content
字段中搜索“cat”一词,并在 title
字段中搜索“food”一词的出现情况。
但是,如果你尝试仅在 title
字段中进行搜索,则搜索将失败,并出现错误“无法找到用于搜索的全文索引”,错误代码为 P2030
,因为搜索需要在两个字段上都进行索引。
- MySQL
- 对于 MySQL,需要在使用
schema.prisma
文件中的@@fulltext
参数搜索的任何列中添加索引。为此,必须启用"fullTextIndex"
预览功能。
SELECT * FROM Blog WHERE MATCH(content) AGAINST(${term} IN NATURAL LANGUAGE MODE);
const term = `cat`
const result = await prisma.$queryRawTyped(fullTextSearch(term))