84 lines
2.6 KiB
Go
84 lines
2.6 KiB
Go
package utils
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/goravel/framework/contracts/database/orm"
|
|
"github.com/goravel/framework/facades"
|
|
)
|
|
|
|
// ApplyFulltextSearch 应用全文索引搜索条件
|
|
// column: 要搜索的字段名(如 "request", "content" 等)
|
|
// keyword: 搜索关键词
|
|
// query: ORM 查询对象
|
|
// 返回: 应用了搜索条件的查询对象
|
|
func ApplyFulltextSearch(query orm.Query, column, keyword string) orm.Query {
|
|
if keyword == "" {
|
|
return query
|
|
}
|
|
|
|
// 获取数据库类型
|
|
dbConnection := facades.Config().GetString("database.default", "sqlite")
|
|
isPostgreSQL := dbConnection == "postgres"
|
|
|
|
// 判断是否应该使用全文索引
|
|
// 对于短词(少于3个字符)或包含特殊字符的搜索,使用 LIKE/ILIKE
|
|
// 对于长词,使用全文索引
|
|
useFulltext := len(keyword) >= 3
|
|
|
|
// 检查是否包含特殊字符(逗号、引号、括号等)
|
|
specialChars := []string{",", "\"", "'", "(", ")", "[", "]", "{", "}", ":", ";", "=", "+", "-", "*", "/", "\\", "|", "&", "%", "$", "#", "@", "!", "?", "<", ">", "~", "`"}
|
|
for _, char := range specialChars {
|
|
if strings.Contains(keyword, char) {
|
|
useFulltext = false
|
|
break
|
|
}
|
|
}
|
|
|
|
if useFulltext {
|
|
if isPostgreSQL {
|
|
// PostgreSQL: 使用 pg_trgm 相似度搜索(需要已创建 GIN 索引)
|
|
// 使用 % 操作符进行相似度匹配,阈值默认 0.3
|
|
return query.Where(column+" % ?", keyword)
|
|
} else {
|
|
// MySQL: 使用 ngram 全文索引
|
|
// 注意:需要确保字段已创建全文索引,索引名格式为 ft_{column}
|
|
return query.Where("MATCH("+column+") AGAINST(? IN BOOLEAN MODE)", keyword)
|
|
}
|
|
} else {
|
|
// 短词或包含特殊字符:使用 LIKE/ILIKE
|
|
if isPostgreSQL {
|
|
// PostgreSQL: 使用 ILIKE(不区分大小写)
|
|
return query.Where(column+" ILIKE ?", "%"+keyword+"%")
|
|
} else {
|
|
// MySQL: 使用 LIKE
|
|
return query.Where(column+" LIKE ?", "%"+keyword+"%")
|
|
}
|
|
}
|
|
}
|
|
|
|
// ShouldUseFulltextIndex 判断是否应该使用全文索引
|
|
// keyword: 搜索关键词
|
|
// 返回: true 表示应该使用全文索引,false 表示使用 LIKE/ILIKE
|
|
func ShouldUseFulltextIndex(keyword string) bool {
|
|
if len(keyword) < 3 {
|
|
return false
|
|
}
|
|
|
|
// 检查是否包含特殊字符
|
|
specialChars := []string{",", "\"", "'", "(", ")", "[", "]", "{", "}", ":", ";", "=", "+", "-", "*", "/", "\\", "|", "&", "%", "$", "#", "@", "!", "?", "<", ">", "~", "`"}
|
|
for _, char := range specialChars {
|
|
if strings.Contains(keyword, char) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// IsPostgreSQL 判断当前数据库是否为 PostgreSQL
|
|
func IsPostgreSQL() bool {
|
|
dbConnection := facades.Config().GetString("database.default", "sqlite")
|
|
return dbConnection == "postgres"
|
|
}
|