在 NAS 上部署一个属于个人的磁力搜索引擎

查看 54|回复 6
作者:journey0ad   
前段时间想给 NAS 找点事情做,发现了 Bitmagnet 这个项目,用了几天发现爬虫的部分还不错,但是自带的 webui 有点简陋,有权限敞开、种子数量上来后搜索慢等问题,用起来总是不那么爽
于是花了几天时间用 Nextjs + NextUI 写了个前端界面,顺带也是为了学一下 Next 的开发,界面功能参考了常见的一些磁力搜索引擎,顺带做了夜间模式、多语言、内容预览和搜索分词等功能
详细的部署过程可以看仓库,提供有 Docker Compose 配置可以快速部署,也可以点 Demo 链接体验,Demo 为了避免版权等问题,内容是固定的
仓库地址: https://github.com/journey-ad/Bitmagnet-Next-Web
Demo: https://bitmagnet-next-web.vercel.app/
预览:


下面是一些开发过程的记录:
原版的 Bitmagnet 自带一个 GraphQL 的 api 可以进行搜索,但用下来和 webui 遇到的问题是一样的,数量上去之后普遍搜索时间在几十秒,最重要的是返回的结果数量不准,没办法做分页
关于搜索和索引问题我问过 bitmagnet 的开发者,他回复是已经结合种子标题和文件内容,在 torrent_contents.tsv 里创建了向量索引。研究后发现是先转罗马音然后存的向量,这样好处是可以用 pg 原生支持的 tsquery 来查询,而且转成罗马音后对应中文的是拼音,可以做到错字也能搜到,坏处是只要同音字就能搜到,就算同音字很离谱也是一样
另外就是 bitmagnet 用了 go-unidecode 这个库做罗马音化,但这个库在 node 上没有一比一对应的,转罗马音的过程和 bitmagnet 做不到完全一致,影响搜索效果
综合以上问题,决定自己写后端代码直连 DB 来查询,但之前没怎么搞过后端,更没搞过搜索这种东西,总之边写边测边改,搞出来了 gin 索引+传统 like 模糊匹配+分词,并根据每个关键词的词性确定为必须或非必须,生成对应的 SQL 查询这种野路子方案。至于为什么不上 ES ,还有个考虑是想侵入性的修改尽量少点,后面 bitmagnet 库表结构有升级时好适配,所以没选 ES 这种重的方案
结果比较多的情况下基本在几百毫秒到几秒内就能返回,部分收录少的词可能要跑全表,要等十几秒,这个性能还算能接受,暂时是我能想到的最好的方案了,等有空了研究一下 discuz 之类的论坛怎么做的搜索
chunkingName   
是的,我目前 nas 上爬了三百多万种子,自带的搜索很慢,前几天连续搜索出错了,现在一直报错不进行搜索了,说数据库处于查询状态。试试你这个
pxiphx891   
点赞,这个好
chunkingName   
搜索报这个错,用他原来的 web 搜索正常
发生意外错误
Message: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.
Digest: 1841269720
journey0ad
OP
  
@chunkingName #3
看下容器内的日志?
chunkingName   
@journey0ad date stream content
2024/07/16 14:44:54 stderr }
2024/07/16 14:44:54 stderr digest: '1841269720'
2024/07/16 14:44:54 stderr at async y (/app/.next/server/app/search/page.js:1:11391) {
2024/07/16 14:44:54 stderr at async b (/app/.next/server/app/search/page.js:1:10813)
2024/07/16 14:44:54 stderr at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
2024/07/16 14:44:54 stderr at a (/app/.next/server/chunks/200.js:1:25217)
2024/07/16 14:44:54 stderr Error: Network response was not ok: Internal Server Error
2024/07/16 14:44:54 stderr at async y (/app/.next/server/app/search/page.js:1:11391)
2024/07/16 14:44:54 stderr at async b (/app/.next/server/app/search/page.js:1:10813)
2024/07/16 14:44:54 stderr at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
2024/07/16 14:44:54 stderr at a (/app/.next/server/chunks/200.js:1:25217)
2024/07/16 14:44:54 stderr Error: Network response was not ok: Internal Server Error
2024/07/16 14:44:54 stderr Failed to fetch: Network response was not ok: Internal Server Error
2024/07/16 14:44:54 stdout keywords: [ { _: '$1', keyword: '雷米', required: true } ]
2024/07/16 14:44:54 stderr }
2024/07/16 14:44:54 stderr extraInfo: undefined
2024/07/16 14:44:54 stderr networkError: null,
2024/07/16 14:44:54 stderr clientErrors: [],
2024/07/16 14:44:54 stderr protocolErrors: [],
2024/07/16 14:44:54 stderr ],
2024/07/16 14:44:54 stderr }
2024/07/16 14:44:54 stderr extensions: [Object]
2024/07/16 14:44:54 stderr path: [Array],
2024/07/16 14:44:54 stderr locations: [Array],
2024/07/16 14:44:54 stderr message: 'Failed to execute search query',
2024/07/16 14:44:54 stderr {
2024/07/16 14:44:54 stderr graphQLErrors: [
2024/07/16 14:44:54 stderr at t.next (/app/.next/server/chunks/38.js:1:134768) {
2024/07/16 14:44:54 stderr at b (/app/.next/server/chunks/38.js:1:134267)
2024/07/16 14:44:54 stderr at g (/app/.next/server/chunks/38.js:1:133726)
2024/07/16 14:44:54 stderr at Object.next (/app/.next/server/chunks/38.js:1:39726)
2024/07/16 14:44:54 stderr at Object.then (/app/.next/server/chunks/38.js:1:39598)
2024/07/16 14:44:54 stderr at new Promise ()
2024/07/16 14:44:54 stderr at /app/.next/server/chunks/38.js:1:39631
2024/07/16 14:44:54 stderr at o (/app/.next/server/chunks/38.js:1:39716)
2024/07/16 14:44:54 stderr at /app/.next/server/chunks/38.js:1:76524
2024/07/16 14:44:54 stderr at new t (/app/.next/server/chunks/38.js:1:88954)
2024/07/16 14:44:54 stderr t [ApolloError]: Failed to execute search query
2024/07/16 14:44:54 stderr }
2024/07/16 14:44:54 stderr port: 5433
2024/07/16 14:44:54 stderr address: '192.168.11.2',
2024/07/16 14:44:54 stderr syscall: 'connect',
2024/07/16 14:44:54 stderr code: 'ECONNREFUSED',
2024/07/16 14:44:54 stderr errno: -111,
2024/07/16 14:44:54 stderr at async Object.g [as search] (/app/.next/server/app/api/graphql/route.js:131:107) {
2024/07/16 14:44:54 stderr at async Promise.all (index 1)
2024/07/16 14:44:54 stderr at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
2024/07/16 14:44:54 stderr at /app/node_modules/pg-pool/index.js:45:11
2024/07/16 14:44:54 stderr Error in search resolver: Error: connect ECONNREFUSED 192.168.11.2:5433
2024/07/16 14:44:54 stdout [ '%雷米%', 10, 0 ]
2024/07/16 14:44:54 stdout filtered; -- 从过滤后的数据中查询
2024/07/16 14:44:54 stdout FROM
2024/07/16 14:44:54 stdout END AS files -- 结果别名设为 'files'
2024/07/16 14:44:54 stdout ELSE NULL -- 如果 files_count 为空, 则设置为 NULL
2024/07/16 14:44:54 stdout )
2024/07/16 14:44:54 stdout WHERE torrent_files.info_hash = filtered.info_hash -- 根据 info_hash 匹配文件
2024/07/16 14:44:54 stdout FROM torrent_files
2024/07/16 14:44:54 stdout ))
2024/07/16 14:44:54 stdout 'extension', torrent_files.extension -- 文件扩展名
2024/07/16 14:44:54 stdout 'size', torrent_files.size, -- 文件大小
2024/07/16 14:44:54 stdout 'path', torrent_files.path, -- 文件在种子中的路径
2024/07/16 14:44:54 stdout 'index', torrent_files.index, -- 文件在种子中的索引
2024/07/16 14:44:54 stdout SELECT json_agg(json_build_object(
2024/07/16 14:44:54 stdout -- 如果有数量, 根据 info_hash 查询文件信息到 'files' 列, 聚合成 JSON
2024/07/16 14:44:54 stdout WHEN filtered.files_count IS NOT NULL THEN (
2024/07/16 14:44:54 stdout CASE
2024/07/16 14:44:54 stdout -- 检查 files_count, 是否有文件数量
2024/07/16 14:44:54 stdout filtered.files_count, -- 种子文件数
2024/07/16 14:44:54 stdout filtered.updated_at, -- 更新时间戳
2024/07/16 14:44:54 stdout filtered.created_at, -- 创建时间戳
2024/07/16 14:44:54 stdout filtered.size, -- 种子大小
2024/07/16 14:44:54 stdout filtered.name, -- 种子名称
2024/07/16 14:44:54 stdout filtered.info_hash, -- 种子哈希
2024/07/16 14:44:54 stdout SELECT
2024/07/16 14:44:54 stdout -- 从过滤后的数据中查询文件信息
2024/07/16 14:44:54 stdout )
chunkingName   
@journey0ad 我将默认数据库 5432 改为了 5433 其余的没动 原版网页搜索正常,你的这个报日志这些错误
您需要登录后才可以回帖 登录 | 立即注册

返回顶部