slow query optimization

This commit is contained in:
mubai
2026-04-22 16:52:59 +08:00
parent 3e6db8b5d6
commit 3fd906a73e
21 changed files with 191 additions and 125 deletions

View File

@@ -73,7 +73,7 @@
</template>
<script lang="ts" setup>
import {inject, onMounted, reactive, ref, watch} from "vue";
import {inject, onMounted, onUnmounted, reactive, ref, watch} from "vue";
import {useRouter} from "vue-router";
import {Search, CircleClose, CircleCloseFilled } from '@element-plus/icons-vue'
import {ElMessage} from "element-plus";
@@ -103,6 +103,7 @@ const data = reactive({
drawer: false,
})
// 获取侧边菜单的挂载元素
const el = document.getElementsByClassName('main')[0]
@@ -169,6 +170,8 @@ onMounted(() => {
})
</script>
@@ -289,7 +292,7 @@ onMounted(() => {
font-weight: 600;
font-style: italic;
font-size: 24px;
margin-right: 5px;
margin-right: 12px;
background: linear-gradient(118deg, #e91a90, #c965b3, #988cd7, #00acfd);
-webkit-background-clip: text;
background-clip: text;

View File

@@ -1,13 +1,13 @@
<template>
<el-container>
<el-header>
<el-header v-show="!data.isNavHidden">
<Header/>
<!--<NewHeader />-->
</el-header>
<el-main>
<router-view></router-view>
</el-main>
<el-footer>
<el-footer v-show="!data.isNavHidden">
<Footer/>
</el-footer>
</el-container>
@@ -16,9 +16,14 @@
<script setup lang="ts">
import Header from "../components/index/Header.vue";
import Footer from "../components/index/Footer.vue";
import {provide} from "vue";
import {onMounted, onUnmounted, provide, reactive} from "vue";
// import NewHeader from "../components/index/NewHeader.vue";
// 页面数据
const data = reactive({
lastScrollTop: 0,
isNavHidden: false,
})
// 在全局注入一个当前是pc还是wrap的状态
const userAgent = navigator.userAgent.toLowerCase()
@@ -26,6 +31,34 @@ let isMobile = /Mobile|Tablet|Android|iPhone|iPad|iPod|BlackBerry|webOS|Windows
// 传递一个全局状态对象
provide('global', {isMobile: isMobile})
//
// 导航栏显示状态控制
const handleScroll = ()=>{
// 获取当前滚动条距离顶部的距离
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
// 只有当滚动超过一定距离例如100px后才开始判断避免在顶部微小滚动时触发
if (scrollTop > 200) {
data.isNavHidden = scrollTop > data.lastScrollTop;
} else {
// 滚动到顶部附近时,始终显示导航栏
data.isNavHidden = false;
}
// 更新上一次的滚动位置
data.lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; // 防止负值
}
// 页面挂载完成时添加监听事件
onMounted(()=>{
// 添加页面滚动监听, 用于导航栏隐藏状态
window.addEventListener('scroll', handleScroll);
})
// 卸载时取消页面滚动监听
onUnmounted(()=>{
window.removeEventListener('scroll', handleScroll);
})
</script>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -11,8 +11,8 @@
<meta charset="UTF-8"/>
<title>o(^▽^)o</title>
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_3992367_d1lr2rjk376.css">
<script type="module" crossorigin src="/assets/index-DFwizkwH.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-hjx10UP7.css">
<script type="module" crossorigin src="/assets/index-LJDx1F2A.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BTtbgUmX.css">
</head>
<body>
<div id="app"></div>

View File

@@ -1,5 +1,3 @@
version: '3.8'
services:
nginx:
container_name: film_nginx

View File

@@ -84,10 +84,20 @@ server
### 本地运行
1. 修改 /server/plugin/db 目录下的 mysql.goredis.go 中的连接地址和用户名密码
2. 在 server 目录下执行 `go run main.go`
1. 数据库初始化, 本地需要有 MySQLRedis 数据库, MySQL中需手动创建名为 `FilmSite` 的数据库
2. 修改 `server/config/DataConfig.go` 目录下的 mysql.go 和 redis.go 中的连接地址和用户名密码
```go
// mysql连接配置信息
MysqlDsn = "root:root@(192.168.20.5:3601)/FilmSite?charset=utf8mb4&parseTime=True&loc=Local"
// redis连接配置信息
RedisAddr = `192.168.20.5:3602`
RedisPassword = `root`
RedisDBNo = 0
```
3. 在 server 目录下执行 `go run main.go`

View File

@@ -57,10 +57,10 @@ require (
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
golang.org/x/arch v0.22.0 // indirect
golang.org/x/crypto v0.48.0 // indirect
golang.org/x/crypto v0.49.0 // indirect
golang.org/x/net v0.51.0 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.34.0 // indirect
golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.36.10 // indirect
)

View File

@@ -140,8 +140,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
@@ -179,8 +179,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -201,8 +201,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=

View File

@@ -192,7 +192,7 @@ func AddSlaveMovieInfoIndex() {
// 如果不存在索引则创建对应索引
if !db.Mdb.Migrator().HasIndex(&s, "idx_mid") {
// 添加索引
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_sid ON %s (sid DESC)", tableName))
//db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_sid ON %s (sid DESC)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_mid ON %s (mid DESC)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_dbId ON %s (db_id DESC", tableName))
}
@@ -730,7 +730,8 @@ func GetRelateMovieBasicInfo(search SearchInfo, page *Page) []MovieBasicInfo {
// 优先进行名称相似匹配, 先对影片名称进行精简, 只保留主体用于匹配同系列影片
name := util.CleanFilmName(search.Name)
sql = fmt.Sprintf(`select mid from %s where (name LIKE "%%%s%%" or sub_title LIKE "%%%[2]s%%") AND cid=%d AND search.deleted_at IS NULL union`, search.TableName(), name, search.Cid)
//sql = fmt.Sprintf(`select mid from %s where (name LIKE "%%%s%%" or sub_title LIKE "%%%[2]s%%") AND cid=%d AND search.deleted_at IS NULL union`, search.TableName(), name, search.Cid)
sql = fmt.Sprintf(`select mid from %s where MATCH(name, sub_title) AGAINST('%s') AND cid=%d AND search.deleted_at IS NULL union`, search.TableName(), name, search.Cid)
// 添加其他相似匹配规则 同属二级分类
sql = fmt.Sprintf(`%s (select mid from %s where cid=%d AND `, sql, search.TableName(), search.Cid)
@@ -792,7 +793,10 @@ func GetMultiplePlay(mIds []string, dbId int64) []SlaveMovieInfo {
}
// 如果迭代完s依旧为空,则去mysql中进行匹配
if s.Mid == "" {
if err := db.Mdb.Model(&SlaveMovieInfo{}).Select("sid, play_list").Where("sid = ? AND (mid IN (?) OR db_id = ?)", c.Id, mIds, dbId).First(&s).Error; err != nil {
//if err := db.Mdb.Model(&SlaveMovieInfo{}).Select("sid, play_list").Where("sid = ? AND (mid IN (?) OR db_id = ?)", c.Id, mIds, dbId).First(&s).Error; err != nil {
//mq := db.Mdb.Model(&SlaveMovieInfo{}).Select("sid, play_list").Where("sid = ? AND mid IN (?)", c.Id, dbId).Limit(1)
//dq := db.Mdb.Model(&SlaveMovieInfo{}).Select("sid, play_list").Where("sid = ? AND db_id = ?", c.Id, dbId).Limit(1)
if err := db.Mdb.Raw("(SELECT sid, play_list FROM `slave_infos` WHERE sid = ? AND mid IN (?)) UNION ALL (SELECT sid, play_list FROM `slave_infos` WHERE sid = ? AND db_id = ? ORDER BY `slave_infos`.`id` LIMIT 1) LIMIT 1", c.Id, mIds, c.Id, dbId).First(&s).Error; err != nil {
log.Println("GetMultiplePlay Failed: ", err)
continue
}

View File

@@ -74,14 +74,17 @@ func AddSearchIndex() {
var s SearchInfo
tableName := s.TableName()
// 添加索引
db.Mdb.Exec(fmt.Sprintf("CREATE UNIQUE INDEX idx_mid ON %s (mid)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_pid ON %s (pid)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_cid ON %s (cid)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_time ON %s (update_stamp DESC)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_hits ON %s (hits DESC)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_score ON %s (score DESC)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_release ON %s (release_stamp DESC)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_year ON %s (year DESC)", tableName))
//db.Mdb.Exec(fmt.Sprintf("CREATE UNIQUE INDEX idx_mid ON %s (mid)", tableName)
//db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_pid ON %s (pid)", tableName))
//db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_cid ON %s (cid)", tableName))
//db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_time ON %s (update_stamp DESC)", tableName))
//db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_hits ON %s (hits DESC)", tableName))
//db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_score ON %s (score DESC)", tableName))
//db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_release ON %s (release_stamp DESC)", tableName))
//db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_year ON %s (year DESC)", tableName))
// 一次执行完所有索引的创建
db.Mdb.Exec(fmt.Sprintf("ALTER TABLE %s ADD UNIQUE INDEX idx_mid (mid DESC), ADD INDEX idx_pid (pid), ADD INDEX idx_cid (cid), ADD INDEX idx_time (update_stamp DESC), ADD INDEX idx_hits (hits DESC), ADD INDEX idx_score (score DESC), ADD INDEX idx_release (release_stamp DESC), ADD INDEX idx_year (year DESC), ADD FULLTEXT INDEX idx_names (name, sub_title) WITH PARSER ngram", tableName))
}
@@ -289,7 +292,7 @@ func BatchSaveOrUpdate(ml []MovieDetail) error {
if err != nil {
log.Println("Save Search Info error: ", err)
}
break
continue
}
// 如果不存在对应信息则保存一份tag
BatchHandleSearchTag(s)

View File

@@ -25,6 +25,7 @@ func FilmSourceInit() {
{Id: util.GenerateSalt(), Name: "HD(BF)", Uri: `https://bfzyapi.com/api.php/provide/vod/`, ResultModel: system.JsonResult, Grade: system.SlaveCollect, SyncPictures: false, CollectType: system.CollectVideo, State: false, Interval: 2500},
{Id: util.GenerateSalt(), Name: "HD(FF)", Uri: `http://cj.ffzyapi.com/api.php/provide/vod/`, ResultModel: system.JsonResult, Grade: system.SlaveCollect, SyncPictures: false, CollectType: system.CollectVideo, State: false},
{Id: util.GenerateSalt(), Name: "HD(OK)", Uri: `https://api.okzyw.net/api.php/provide/vod/`, ResultModel: system.JsonResult, Grade: system.SlaveCollect, SyncPictures: false, CollectType: system.CollectVideo, State: false},
{Id: util.GenerateSalt(), Name: "HD(MD)", Uri: `https://www.mdzyapi.com/api.php/provide/vod/`, ResultModel: system.JsonResult, Grade: system.SlaveCollect, SyncPictures: false, CollectType: system.CollectVideo, State: false},
{Id: util.GenerateSalt(), Name: "HD(LY)", Uri: `https://360zy.com/api.php/provide/vod/at/json`, ResultModel: system.JsonResult, Grade: system.SlaveCollect, SyncPictures: false, CollectType: system.CollectVideo, State: false},
{Id: util.GenerateSalt(), Name: "HD(SN)", Uri: `https://suoniapi.com/api.php/provide/vod/from/snm3u8/`, ResultModel: system.JsonResult, Grade: system.SlaveCollect, SyncPictures: false, CollectType: system.CollectVideo, State: false, Interval: 2000},
{Id: util.GenerateSalt(), Name: "HD(DB)", Uri: `https://caiji.dbzy.tv/api.php/provide/vod/from/dbm3u8/at/josn/`, ResultModel: system.JsonResult, Grade: system.SlaveCollect, SyncPictures: false, CollectType: system.CollectVideo, State: false},

View File

@@ -26,10 +26,10 @@ func BasicConfigInit() {
func BannersInit() {
var bl = system.Banners{
system.Banner{Id: util.GenerateSalt(), Name: "樱花庄的宠物女孩", Year: 2020, CName: "日韩动漫", Poster: "https://s2.loli.net/2024/02/21/Wt1QDhabdEI7HcL.jpg", Picture: "https://img.bfzypic.com/upload/vod/20230424-43/06e79232a4650aea00f7476356a49847.jpg", Remark: "已完结"},
system.Banner{Id: util.GenerateSalt(), Name: "从零开始的异世界生活", Year: 2020, CName: "日韩动漫", Poster: "https://s2.loli.net/2024/02/21/UkpdhIRO12fsy6C.jpg", Picture: "https://img.bfzypic.com/upload/vod/20230424-43/06e79232a4650aea00f7476356a49847.jpg", Remark: "已完结"},
system.Banner{Id: util.GenerateSalt(), Name: "五等分的花嫁", Year: 2020, CName: "日韩动漫", Poster: "https://s2.loli.net/2024/02/21/wXJr59Zuv4tcKNp.jpg", Picture: "https://img.bfzypic.com/upload/vod/20230424-43/06e79232a4650aea00f7476356a49847.jpg", Remark: "已完结"},
system.Banner{Id: util.GenerateSalt(), Name: "我的青春恋爱物语果然有问题", Year: 2020, CName: "日韩动漫", Poster: "https://s2.loli.net/2024/02/21/oMAGzSliK2YbhRu.jpg", Picture: "https://img.bfzypic.com/upload/vod/20230424-43/06e79232a4650aea00f7476356a49847.jpg", Remark: "已完结"},
system.Banner{Id: util.GenerateSalt(), Name: "樱花庄的宠物女孩", Year: 2020, CName: "日韩动漫", Poster: "https://pic1.imgdb.cn/item/69e441783c746ca9770a03ce.jpg", Picture: "https://img.bfzypic.com/upload/vod/20230424-43/06e79232a4650aea00f7476356a49847.jpg", Remark: "已完结"},
system.Banner{Id: util.GenerateSalt(), Name: "从零开始的异世界生活", Year: 2020, CName: "日韩动漫", Poster: "https://pic1.imgdb.cn/item/69e441793c746ca9770a03d1.jpg", Picture: "https://img.bfzypic.com/upload/vod/20230424-43/06e79232a4650aea00f7476356a49847.jpg", Remark: "已完结"},
system.Banner{Id: util.GenerateSalt(), Name: "五等分的花嫁", Year: 2020, CName: "日韩动漫", Poster: "https://pic1.imgdb.cn/item/69e441793c746ca9770a03d0.jpg", Picture: "https://img.bfzypic.com/upload/vod/20230424-43/06e79232a4650aea00f7476356a49847.jpg", Remark: "已完结"},
system.Banner{Id: util.GenerateSalt(), Name: "我的青春恋爱物语果然有问题", Year: 2020, CName: "日韩动漫", Poster: "https://pic1.imgdb.cn/item/69e441793c746ca9770a03cf.jpg", Picture: "https://img.bfzypic.com/upload/vod/20230424-43/06e79232a4650aea00f7476356a49847.jpg", Remark: "已完结"},
}
_ = system.SaveBanners(bl)
}

View File

@@ -156,10 +156,13 @@ func CleanFilmName(name string) string {
//for rePrefix.MatchString(name) {
// name = rePrefix.ReplaceAllString(name, "")
//}
// 去除名称末尾的空格以及后续内容
name = regexp.MustCompile(`\s+\S*$`).ReplaceAllString(name, "")
// 2.定义需要清洗的特殊标识关键字集合
var noisePatterns = []string{
` [零一二三四五六七八九十\d]+ `, ` [零一二三四五六七八九十\d]+ `, ` [零一二三四五六七八九十\d]+ `,
`Season\s*\d+`, `S\d+`, `Ep\d+`, `\d{1,3}\s*(话 | 集)`,
`第[零一二三四五六七八九十\d]+季`, `第[零一二三四五六七八九十\d]+话`, `第[零一二三四五六七八九十\d]+集`,
`Season\s*\d+`, `S\d+`, `Ep\d+`, `\d{1,3}\s*(话|集)`,
`\s+(II|III|IV|V|VI|VII|VIII|IX|X)\s*$`,
`剧场版`, `电影版`, `OVA`, `OAD`, `SP`, `特别篇`, `总集篇`, `外传`, ``, ``, ``, `终章`,
`\d{3,4}[Pp]`, `HD`, `FHD`, `UHD`, `4K`, `BD`, `BluRay`, `BDRip`, `HEVC`, `H264`, `H265`,
@@ -168,7 +171,7 @@ func CleanFilmName(name string) string {
`Uncensored`, `NoCen`, `Dubbed`, `Subbed`, `Raw`, `生肉`, `熟肉`,
}
// 3. 处理拼接完整的正则表达式
fullPattern := `(?i)(?:\s+|\.+|_+|-+) (` + strings.Join(noisePatterns, "|") + `).*$`
fullPattern := `(?i)(?:\s*|\.+|_+|-+)*(` + strings.Join(noisePatterns, "|") + `).*$`
cutRegex := regexp.MustCompile(fullPattern)
// 去除满足匹配集的子串
name = cutRegex.ReplaceAllString(name, "")

View File

@@ -26,9 +26,9 @@ func InitMysql() (err error) {
SingularTable: true, //是否使用 结构体名称作为表名 (关闭自动变复数)
//NameReplacer: strings.NewReplacer("spider_", ""), // 替表名和字段中的 Me 为 空
},
//Logger: logger.Default.LogMode(logger.Warn), //设置日志级别为Info
//Logger: logger.Default.LogMode(logger.Info), //设置日志级别为Info
Logger: logger.Default.LogMode(logger.Error), //设置日志级别为Info
//Logger: logger.Default.LogMode(logger.Warn), //设置日志级别为 Warn
Logger: logger.Default.LogMode(logger.Info), //设置日志级别为Info
//Logger: logger.Default.LogMode(logger.Error), //设置日志级别为 Error
})
return
}

View File

@@ -192,7 +192,7 @@ func AddSlaveMovieInfoIndex() {
// 如果不存在索引则创建对应索引
if !db.Mdb.Migrator().HasIndex(&s, "idx_mid") {
// 添加索引
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_sid ON %s (sid DESC)", tableName))
//db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_sid ON %s (sid DESC)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_mid ON %s (mid DESC)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_dbId ON %s (db_id DESC", tableName))
}
@@ -730,7 +730,8 @@ func GetRelateMovieBasicInfo(search SearchInfo, page *Page) []MovieBasicInfo {
// 优先进行名称相似匹配, 先对影片名称进行精简, 只保留主体用于匹配同系列影片
name := util.CleanFilmName(search.Name)
sql = fmt.Sprintf(`select mid from %s where (name LIKE "%%%s%%" or sub_title LIKE "%%%[2]s%%") AND cid=%d AND search.deleted_at IS NULL union`, search.TableName(), name, search.Cid)
//sql = fmt.Sprintf(`select mid from %s where (name LIKE "%%%s%%" or sub_title LIKE "%%%[2]s%%") AND cid=%d AND search.deleted_at IS NULL union`, search.TableName(), name, search.Cid)
sql = fmt.Sprintf(`select mid from %s where MATCH(name, sub_title) AGAINST('%s') AND cid=%d AND search.deleted_at IS NULL union`, search.TableName(), name, search.Cid)
// 添加其他相似匹配规则 同属二级分类
sql = fmt.Sprintf(`%s (select mid from %s where cid=%d AND `, sql, search.TableName(), search.Cid)
@@ -792,7 +793,10 @@ func GetMultiplePlay(mIds []string, dbId int64) []SlaveMovieInfo {
}
// 如果迭代完s依旧为空,则去mysql中进行匹配
if s.Mid == "" {
if err := db.Mdb.Model(&SlaveMovieInfo{}).Select("sid, play_list").Where("sid = ? AND (mid IN (?) OR db_id = ?)", c.Id, mIds, dbId).First(&s).Error; err != nil {
//if err := db.Mdb.Model(&SlaveMovieInfo{}).Select("sid, play_list").Where("sid = ? AND (mid IN (?) OR db_id = ?)", c.Id, mIds, dbId).First(&s).Error; err != nil {
//mq := db.Mdb.Model(&SlaveMovieInfo{}).Select("sid, play_list").Where("sid = ? AND mid IN (?)", c.Id, dbId).Limit(1)
//dq := db.Mdb.Model(&SlaveMovieInfo{}).Select("sid, play_list").Where("sid = ? AND db_id = ?", c.Id, dbId).Limit(1)
if err := db.Mdb.Raw("(SELECT sid, play_list FROM `slave_infos` WHERE sid = ? AND mid IN (?)) UNION ALL (SELECT sid, play_list FROM `slave_infos` WHERE sid = ? AND db_id = ? ORDER BY `slave_infos`.`id` LIMIT 1) LIMIT 1", c.Id, mIds, c.Id, dbId).First(&s).Error; err != nil {
log.Println("GetMultiplePlay Failed: ", err)
continue
}

View File

@@ -74,14 +74,17 @@ func AddSearchIndex() {
var s SearchInfo
tableName := s.TableName()
// 添加索引
db.Mdb.Exec(fmt.Sprintf("CREATE UNIQUE INDEX idx_mid ON %s (mid)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_pid ON %s (pid)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_cid ON %s (cid)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_time ON %s (update_stamp DESC)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_hits ON %s (hits DESC)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_score ON %s (score DESC)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_release ON %s (release_stamp DESC)", tableName))
db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_year ON %s (year DESC)", tableName))
//db.Mdb.Exec(fmt.Sprintf("CREATE UNIQUE INDEX idx_mid ON %s (mid)", tableName)
//db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_pid ON %s (pid)", tableName))
//db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_cid ON %s (cid)", tableName))
//db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_time ON %s (update_stamp DESC)", tableName))
//db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_hits ON %s (hits DESC)", tableName))
//db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_score ON %s (score DESC)", tableName))
//db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_release ON %s (release_stamp DESC)", tableName))
//db.Mdb.Exec(fmt.Sprintf("CREATE INDEX idx_year ON %s (year DESC)", tableName))
// 一次执行完所有索引的创建
db.Mdb.Exec(fmt.Sprintf("ALTER TABLE %s ADD UNIQUE INDEX idx_mid (mid DESC), ADD INDEX idx_pid (pid), ADD INDEX idx_cid (cid), ADD INDEX idx_time (update_stamp DESC), ADD INDEX idx_hits (hits DESC), ADD INDEX idx_score (score DESC), ADD INDEX idx_release (release_stamp DESC), ADD INDEX idx_year (year DESC), ADD FULLTEXT INDEX idx_names (name, sub_title) WITH PARSER ngram", tableName))
}
@@ -289,7 +292,7 @@ func BatchSaveOrUpdate(ml []MovieDetail) error {
if err != nil {
log.Println("Save Search Info error: ", err)
}
break
continue
}
// 如果不存在对应信息则保存一份tag
BatchHandleSearchTag(s)

View File

@@ -25,6 +25,7 @@ func FilmSourceInit() {
{Id: util.GenerateSalt(), Name: "HD(BF)", Uri: `https://bfzyapi.com/api.php/provide/vod/`, ResultModel: system.JsonResult, Grade: system.SlaveCollect, SyncPictures: false, CollectType: system.CollectVideo, State: false, Interval: 2500},
{Id: util.GenerateSalt(), Name: "HD(FF)", Uri: `http://cj.ffzyapi.com/api.php/provide/vod/`, ResultModel: system.JsonResult, Grade: system.SlaveCollect, SyncPictures: false, CollectType: system.CollectVideo, State: false},
{Id: util.GenerateSalt(), Name: "HD(OK)", Uri: `https://api.okzyw.net/api.php/provide/vod/`, ResultModel: system.JsonResult, Grade: system.SlaveCollect, SyncPictures: false, CollectType: system.CollectVideo, State: false},
{Id: util.GenerateSalt(), Name: "HD(MD)", Uri: `https://www.mdzyapi.com/api.php/provide/vod/`, ResultModel: system.JsonResult, Grade: system.SlaveCollect, SyncPictures: false, CollectType: system.CollectVideo, State: false},
{Id: util.GenerateSalt(), Name: "HD(LY)", Uri: `https://360zy.com/api.php/provide/vod/at/json`, ResultModel: system.JsonResult, Grade: system.SlaveCollect, SyncPictures: false, CollectType: system.CollectVideo, State: false},
{Id: util.GenerateSalt(), Name: "HD(SN)", Uri: `https://suoniapi.com/api.php/provide/vod/from/snm3u8/`, ResultModel: system.JsonResult, Grade: system.SlaveCollect, SyncPictures: false, CollectType: system.CollectVideo, State: false, Interval: 2000},
{Id: util.GenerateSalt(), Name: "HD(DB)", Uri: `https://caiji.dbzy.tv/api.php/provide/vod/from/dbm3u8/at/josn/`, ResultModel: system.JsonResult, Grade: system.SlaveCollect, SyncPictures: false, CollectType: system.CollectVideo, State: false},

View File

@@ -156,10 +156,13 @@ func CleanFilmName(name string) string {
//for rePrefix.MatchString(name) {
// name = rePrefix.ReplaceAllString(name, "")
//}
// 去除名称末尾的空格以及后续内容
name = regexp.MustCompile(`\s+\S*$`).ReplaceAllString(name, "")
// 2.定义需要清洗的特殊标识关键字集合
var noisePatterns = []string{
` [零一二三四五六七八九十\d]+ `, ` [零一二三四五六七八九十\d]+ `, ` [零一二三四五六七八九十\d]+ `,
`Season\s*\d+`, `S\d+`, `Ep\d+`, `\d{1,3}\s*(话 | 集)`,
`第[零一二三四五六七八九十\d]+季`, `第[零一二三四五六七八九十\d]+话`, `第[零一二三四五六七八九十\d]+集`,
`Season\s*\d+`, `S\d+`, `Ep\d+`, `\d{1,3}\s*(话|集)`,
`\s+(II|III|IV|V|VI|VII|VIII|IX|X)\s*$`,
`剧场版`, `电影版`, `OVA`, `OAD`, `SP`, `特别篇`, `总集篇`, `外传`, ``, ``, ``, `终章`,
`\d{3,4}[Pp]`, `HD`, `FHD`, `UHD`, `4K`, `BD`, `BluRay`, `BDRip`, `HEVC`, `H264`, `H265`,
@@ -168,7 +171,7 @@ func CleanFilmName(name string) string {
`Uncensored`, `NoCen`, `Dubbed`, `Subbed`, `Raw`, `生肉`, `熟肉`,
}
// 3. 处理拼接完整的正则表达式
fullPattern := `(?i)(?:\s+|\.+|_+|-+) (` + strings.Join(noisePatterns, "|") + `).*$`
fullPattern := `(?i)(?:\s*|\.+|_+|-+)*(` + strings.Join(noisePatterns, "|") + `).*$`
cutRegex := regexp.MustCompile(fullPattern)
// 去除满足匹配集的子串
name = cutRegex.ReplaceAllString(name, "")

View File

@@ -26,9 +26,9 @@ func InitMysql() (err error) {
SingularTable: true, //是否使用 结构体名称作为表名 (关闭自动变复数)
//NameReplacer: strings.NewReplacer("spider_", ""), // 替表名和字段中的 Me 为 空
},
//Logger: logger.Default.LogMode(logger.Warn), //设置日志级别为Info
//Logger: logger.Default.LogMode(logger.Info), //设置日志级别为Info
Logger: logger.Default.LogMode(logger.Error), //设置日志级别为Info
//Logger: logger.Default.LogMode(logger.Warn), //设置日志级别为 Warn
Logger: logger.Default.LogMode(logger.Info), //设置日志级别为Info
//Logger: logger.Default.LogMode(logger.Error), //设置日志级别为 Error
})
return
}