typecho 原生搜索的效率真的很低,看到熊猫小A的这个插件Typecho 搜索增强:ExSearch,效果真的很棒!
于是开始了一些研究,准备用在自己的主题上。
熊猫小A的插件具体的实现原理是:
- 插件中生成整个数据库文章的json数据(并使用typecho的钩子可以保证在发表新文章、修改文章中时候同步更新数据),这个数据有两种方式存储(文件形式,数据库)
- 博客打开的时候就会加载到这个json数据到前端
- 搜索的时候直接拿这个json数据进行匹配就可以了
但我把代码用到我的博客上的时候,出现了一些问题。
当文章数目很多的时候(我的博客目前是217篇文章),生成的json数据大小是很大的,我生成之后是1.9M的大小,使用jquery的 getjson方法很耗时(我测试是19s,和服务器有关,虽然不阻碍页面渲染)
于是产生两个问题:
- 在json数据在请求的这个过程中,搜索功能是没办法用的
- json数据过大造成的流量问题
(熊猫小A是一打开博客就开始请求这个json文件,我个人觉得搜索其实并不是一个常用功能,所以我是点击搜索框才开始请求这个json数据)
当然上面两个问题不是特别大的问题。
但是如果你的博客的文章非常之多!这个json数据会很大,导致的请求读取时间就可能非常长了,而且造成不必要的流量加载。
我的解决方法是:前端不要一次性加载整个文章的json数据,而是通过php使用SEESION变量存储读取缓存的json数据。
if ($_SESSION['search_cache'] === false){
$object['status'] = false;
//这部分如果数据是存储在数据库中,就从数据库中读取,我这里是从缓存文件中读取
$filePath = __TYPECHO_ROOT_DIR__ . __TYPECHO_PLUGIN_DIR__ . DIRECTORY_SEPARATOR.'Handsome'.DIRECTORY_SEPARATOR.'cache'.DIRECTORY_SEPARATOR.'search.json';
$file = file_get_contents($filePath);
if ($file === false){
$fail = "{}";
$_SESSION['search_cache'] = $fail;
echo $fail;
}else{
$_SESSION['search_cache'] = $file;
}
}else{
$object['status'] = true;
}
//处理搜索数据,返回结果
...
通过监控输入框的值,不断发起ajax请求,后端直接使用SEESION变量的值进行返回结果就可以。
优点: 多次搜索,只需要一次读取文件的消耗(之后使用SEESION变量)
缺点: 多次搜索会有多次ajax请求(但这个ajax请求不会读数据库,也不会读文件,总体来说消耗是非常小的,所以速度也是很快的)
(之前实现也是监控输入值发起ajax请求,只不过每次ajax请求都会操作数据库,这个速度很慢)
当然这种方法也只是一种权衡罢了,毕竟ajax请求再快也会受服务器是否阻塞和网络原因影响,而一开始就加载好全部的json数据则真正达到“即时搜索”。
具体效果可以看现在我的博客。
如果有更好想法欢迎在评论区讨论~
22 条评论
牛逼了
这篇教程基于这款插件提供了许多具有可行性的建议,很棒,我转载了。
https://www.npc.ink/14772.html
博主大佬,我用的是hran的主题,使用这个插件之后也发现一个问题,就是重建索引第一次之后,点击搜索还是有效果的,但是在一个新页面或者新设备上打开搜索,什么都不显示,连搜索的功能都没了,是不是就是因为文章内容过多导致的呢!
需要pjax适配一下的
algolia 搜索似乎也很不错,还节省了服务器资源,考虑下?
如果博文过多,其实可以考虑后端输出所有文章压缩,前端字符串解压,前端js将压缩后的文本储存在localStorage里,设置存活时间,localStorage容量为5MB,可以存放很多,后期如果是在文章太多,就需要考虑文章即时搜索取舍,我理解的权重如下:文章标签>文章标题>文章索引,而不是去全文检索,即时搜索毕竟是辅助性,主要还是用户的回车搜索...我最近打算的是这样对自己写的即时搜索做更改.
厉害了,学习了
handsome更新会考虑聚合么,用插件会影响加载速度
会的
要是能给出后端代码就再好不过啦!
网页打开有点问题,点几次都点不开。
目前搜索框输入关键词后,如不选即时搜索给出的列表内容,单靠鼠标是无法执行搜索功能的(鼠标点击放大镜无任何作用),只有回车键(Enter)才能完成搜索。这是否是一个bug?
即时搜索结果就是最终结果 无需再点击放大镜图标搜索了
这个插件我也用过,不过因为服务器速度还行,所以改成了异步加载的方式,不过后来还是放弃了,大概是懒得改样式吧→_→
另外,session 默认情况下本质上还是文件存储,接口执行完毕返回的时候会把session中的内容回写到临时文件里,所以这么一来一回的感觉上有点多余,还不如直接读取文件
我又逮到hran了,什么时候把这个插件也和主题兼容下,这个真的好棒
读文件的速度我觉得就差不多了,或者把数据存到数据库,时间差不多的
我有个想法,但只是停留在想法,没去验证
Typecho 的模板结构是可以自定义 search.php 的,我异想天开可以把 search.php 改成 json 输出方式那种,然后前端 ajax 请求 site.com/search/{$contents}/ 实现搜索。
具体可不可行 也是未知数 毕竟刚刚想到
如果怕有直接访问 /search/ 的情况,在 search.php 中加个 $_GET["search"] 的判断,如果传过来 search 就出 json 没传的话直接输出模板原来的内容
勿喷qwq
我现在差不多就是这个思路,只是没用到search.php 这个文件,而另写了一个接口 来ajax请求数据
生成文件太大了,我还是老老实实用官方默认的吧。
感觉 8 错,其实我也想过把 ExSearch 把到我主题上来着