跳過主內容

全文搜尋

Prisma Client 支援對 PostgreSQL 資料庫(2.30.0 及更高版本)和 MySQL 資料庫(3.8.0 及更高版本)進行全文搜尋。啟用全文搜尋 (FTS) 後,你可以在資料庫列中搜索文字,從而為你的應用程式新增搜尋功能。

資訊

在 Prisma v6 中,FTS 已在 MySQL 上 提升為通用可用。對於 PostgreSQL,它仍然是預覽功能,並且需要使用 fullTextSearchPostgres 預覽功能標誌。

為 PostgreSQL 啟用全文搜尋

全文搜尋 API 目前是預覽功能。要啟用此功能,請執行以下步驟:

  1. 更新你的 schema 中的 previewFeatures 塊,以包含 fullTextSearchPostgres 預覽功能標誌

    schema.prisma
    generator client {
    provider = "prisma-client-js"
    previewFeatures = ["fullTextSearchPostgres"]
    }
  2. 生成 Prisma Client

    npx prisma generate

重新生成客戶端後,你模型上建立的任何 String 欄位都將提供一個新的 search 欄位。例如,以下搜尋將返回所有包含單詞 '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',
},
},
})

為了理解查詢格式的工作原理,請考慮以下文字:

“敏捷的棕狐躍過懶狗”

以下查詢將如何匹配該文字:

查詢匹配?解釋
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',
},
},
})

為了理解查詢格式的工作原理,請考慮以下文字:

“敏捷的棕狐躍過懶狗”

以下查詢將如何匹配該文字:

查詢匹配?描述
+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. “敏捷的棕狐躍過懶狗”

2. “敏捷的棕狐躍過懶貓”

查詢結果描述
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 問題

MySQL

對於 MySQL,有必要在 schema.prisma 檔案中使用 @@fulltext 引數為你搜索的任何列新增索引。

在以下示例中,一個全文索引被新增到 Blog 模型的 content 欄位,另一個則同時新增到 contenttitle 欄位。

schema.prisma
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',
},
},
})

第二個索引允許同時在 contenttitle 欄位中搜索 content 中包含 'cat' 且 title 中包含 'food' 的出現。

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

然而,如果你嘗試單獨搜尋 title,搜尋將失敗,並出現錯誤“Cannot find a fulltext index to use for the search”,訊息程式碼為 P2030,因為此搜尋需要兩個欄位上的索引。

使用原生 SQL 進行全文搜尋

全文搜尋目前處於預覽階段,並且由於存在一個已知問題,你可能會遇到慢速搜尋查詢。如果是這樣,你可以使用 TypedSQL 來最佳化你的查詢。

PostgreSQL

使用 TypedSQL,你可以使用 PostgreSQL 的 to_tsvectorto_tsquery 來表達你的搜尋查詢。

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

注意:根據你的語言偏好,你可以在 SQL 語句中將 english 替換為其他語言。

如果你想在搜尋詞中包含萬用字元,可以按如下方式操作:

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

MySQL

在 MySQL 中,你可以按如下方式表達你的搜尋查詢:

SELECT * FROM Blog WHERE MATCH(content) AGAINST(${term} IN NATURAL LANGUAGE MODE);
© . This site is unofficial and not affiliated with Prisma Data, Inc.