全文檢索
Prisma Client 在 2.30.0 及更高版本中支援 PostgreSQL 資料庫的全文檢索,以及在 3.8.0 及更高版本中支援 MySQL 資料庫的全文檢索。啟用全文檢索 (FTS) 後,您可以透過搜尋資料庫欄位中的文字,將搜尋功能新增至您的應用程式。
在 Prisma v6 中,FTS 已在 MySQL 上升級至正式發行 (General Availability)。它仍然是 PostgreSQL 的預覽功能,並且需要使用 fullTextSearchPostgres
預覽功能標誌。
為 PostgreSQL 啟用全文檢索
全文檢索 API 目前是預覽功能。若要啟用此功能,請執行下列步驟
-
更新您 schema 中的
previewFeatures
區塊,以包含fullTextSearchPostgres
預覽功能標誌schema.prismagenerator client {
provider = "prisma-client-js"
previewFeatures = ["fullTextSearchPostgres"]
} -
產生 Prisma Client
npx prisma generate
在您重新產生用戶端之後,新的 search
欄位將在您模型上建立的任何 String
欄位上可用。例如,以下搜尋將傳回所有包含 'cat' 這個詞的貼文。
// All posts that contain the word 'cat'.
const result = await prisma.posts.findMany({
where: {
body: {
search: 'cat',
},
},
})
注意:目前 PostgreSQL 的全文檢索功能存在一個 已知問題。如果您觀察到搜尋查詢速度緩慢,您可以使用原始 SQL 優化您的查詢。
查詢資料庫
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 | 是 | 文字包含 'fox' 或 'cat' |
cat | pig | 否 | 文字不包含 'cat' 或 'pig' |
fox <-> dog | 是 | 'dog' 在文字中跟在 'fox' 之後 |
dog <-> fox | 否 | 'fox' 在文字中不跟在 'dog' 之後 |
如需完整支援的操作範圍,請參閱 PostgreSQL 全文檢索文件。
MySQL
以下範例示範 MySQL 'and' (+
) 和 'not' (-
) 運算子的用法
// 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' |
+dog +fox | 是 | 文字包含 'dog' 和 'fox' |
+dog -cat | 是 | 文字包含 'dog' 但不包含 'cat' |
-cat | 否 | 減號運算子不能單獨使用 (請參閱以下注意事項) |
fox dog | 是 | 文字包含 'fox' 或 'dog' |
quic* | 是 | 文字包含以 'quic' 開頭的單字 |
quick fox @2 | 是 | 'fox' 在 'quick' 的 2 個單字距離內開始 |
fox dog @2 | 否 | 'dog' 不在 'fox' 的 2 個單字距離內開始 |
"jumps over" | 是 | 文字包含完整詞組 'jumps over' |
注意:- 運算子僅用於排除其他搜尋詞彙所比對的列。因此,僅包含以 - 開頭的詞彙的布林模式搜尋會傳回空結果。它不會傳回「除了包含任何排除詞彙的列之外的所有列。」
MySQL 也具有 >
、<
和 ~
運算子,用於變更搜尋結果的排名順序。例如,考慮以下兩個記錄
1. "The quick brown fox jumps over the lazy dog"
2. "The quick brown fox jumps over the lazy cat"
查詢 | 結果 | 描述 |
---|---|---|
fox ~cat | 先傳回 1.,然後傳回 2。 | 傳回所有包含 'fox' 的記錄,但將包含 'cat' 的記錄排名較低 |
fox (<cat >dog) | 先傳回 1.,然後傳回 2。 | 傳回所有包含 'fox' 的記錄,但將包含 'cat' 的記錄排名低於包含 'dog' 的列 |
如需完整支援的操作範圍,請參閱 MySQL 全文檢索文件。
依 _relevance
排序結果
依關聯性排序僅適用於 PostgreSQL 和 MySQL。
除了 Prisma Client 的預設 orderBy
行為 之外,全文檢索也新增了依據給定字串或字串的關聯性排序。例如,如果您想依據貼文標題與詞彙 'database'
的關聯性來排序貼文,您可以使用以下內容
const posts = await prisma.post.findMany({
orderBy: {
_relevance: {
fields: ['title'],
search: 'database',
sort: 'asc'
},
},
})
新增索引
PostgreSQL
Prisma Client 目前不支援使用索引來加速全文檢索。目前有一個關於此問題的 GitHub Issue。
MySQL
對於 MySQL,必須將索引新增至您使用 schema.prisma
檔案中的 @@fulltext
引數搜尋的任何欄位。
在以下範例中,一個全文索引新增至 Blog
模型的 content
欄位,另一個索引一起新增至 content
和 title
欄位
generator client {
provider = "prisma-client-js"
}
model Blog {
id Int @unique
content String
title String
@@fulltext([content])
@@fulltext([content, title])
}
第一個索引允許在 content
欄位中搜尋單字 'cat' 的出現次數
const result = await prisma.blogs.findMany({
where: {
content: {
search: 'cat',
},
},
})
第二個索引允許在 content
和 title
欄位中搜尋單字 'cat' 在 content
中和 'food' 在 title
中的出現次數
const result = await prisma.blogs.findMany({
where: {
content: {
search: 'cat',
},
title: {
search: 'food',
},
},
})
但是,如果您嘗試僅在 title
上搜尋,則搜尋將失敗,並顯示錯誤「找不到要用於搜尋的全文索引」,訊息代碼為 P2030
,因為搜尋需要在兩個欄位上都有索引。
使用原始 SQL 進行全文檢索
全文檢索目前為預覽版,由於 已知問題,您可能會遇到搜尋查詢速度緩慢的問題。如果是這樣,您可以使用 TypedSQL 優化您的查詢。
PostgreSQL
使用 TypedSQL,您可以使用 PostgreSQL 的 to_tsvector
和 to_tsquery
來表示您的搜尋查詢。
- fullTextSearch.sql
- index.ts
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))
注意:根據您的語言偏好,您可以在 SQL 語句中將
english
替換為其他語言。
如果您想在搜尋詞彙中包含萬用字元,您可以依照以下方式操作
- fullTextSearch.sql
- index.ts
SELECT * FROM "Blog" WHERE to_tsvector('english', "Blog"."content") @@ to_tsquery('english', ${term});
const term = `cat:*`
const result = await prisma.$queryRawTyped(fullTextSearch(term))
MySQL
在 MySQL 中,您可以依照以下方式表示您的搜尋查詢
- fullTextSearch.sql
- index.ts
SELECT * FROM Blog WHERE MATCH(content) AGAINST(${term} IN NATURAL LANGUAGE MODE);
const term = `cat`
const result = await prisma.$queryRawTyped(fullTextSearch(term))