typecho 即时搜索解决方案

typecho 原生搜索的效率真的很低,看到熊猫小A的这个插件Typecho 搜索增强:ExSearch,效果真的很棒!

于是开始了一些研究,准备用在自己的主题上。

熊猫小A的插件具体的实现原理是:

  1. 插件中生成整个数据库文章的json数据(并使用typecho的钩子可以保证在发表新文章、修改文章中时候同步更新数据),这个数据有两种方式存储(文件形式,数据库)
  2. 博客打开的时候就会加载到这个json数据到前端
  3. 搜索的时候直接拿这个json数据进行匹配就可以了

但我把代码用到我的博客上的时候,出现了一些问题。


当文章数目很多的时候(我的博客目前是217篇文章),生成的json数据大小是很大的,我生成之后是1.9M的大小,使用jquery的 getjson方法很耗时(我测试是19s,和服务器有关,虽然不阻碍页面渲染)

于是产生两个问题:

  1. 在json数据在请求的这个过程中,搜索功能是没办法用的
  2. 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数据则真正达到“即时搜索”。


具体效果可以看现在我的博客。

如果有更好想法欢迎在评论区讨论~

最后修改:2019 年 07 月 30 日 05 : 48 PM
如果觉得我的文章对你有用,请随意赞赏

16 条评论

  1. 南蜇

    如果博文过多,其实可以考虑后端输出所有文章压缩,前端字符串解压,前端js将压缩后的文本储存在localStorage里,设置存活时间,localStorage容量为5MB,可以存放很多,后期如果是在文章太多,就需要考虑文章即时搜索取舍,我理解的权重如下:文章标签>文章标题>文章索引,而不是去全文检索,即时搜索毕竟是辅助性,主要还是用户的回车搜索...我最近打算的是这样对自己写的即时搜索做更改.

  2. Jdeal

    厉害了,学习了

  3. 何叶

    handsome更新会考虑聚合么,用插件会影响加载速度

    1. 友人C
      @何叶

      会的

  4. MrXiao

    要是能给出后端代码就再好不过啦!

  5. repostone

    网页打开有点问题,点几次都点不开。

  6. 小凡
    该评论仅登录用户及评论双方可见
    1. 友人C
      @小凡
      该评论仅登录用户及评论双方可见
  7. masy

    目前搜索框输入关键词后,如不选即时搜索给出的列表内容,单靠鼠标是无法执行搜索功能的(鼠标点击放大镜无任何作用),只有回车键(Enter)才能完成搜索。这是否是一个bug?

    1. 友人C
      @masy

      即时搜索结果就是最终结果 无需再点击放大镜图标搜索了

  8. Hran

    这个插件我也用过,不过因为服务器速度还行,所以改成了异步加载的方式,不过后来还是放弃了,大概是懒得改样式吧→_→
    另外,session 默认情况下本质上还是文件存储,接口执行完毕返回的时候会把session中的内容回写到临时文件里,所以这么一来一回的感觉上有点多余,还不如直接读取文件

    1. 友人C
      @Hran

      读文件的速度我觉得就差不多了,或者把数据存到数据库,时间差不多的

  9. 尚寂新

    我有个想法,但只是停留在想法,没去验证
    Typecho 的模板结构是可以自定义 search.php 的,我异想天开可以把 search.php 改成 json 输出方式那种,然后前端 ajax 请求 site.com/search/{$contents}/ 实现搜索。
    具体可不可行 也是未知数 毕竟刚刚想到
    如果怕有直接访问 /search/ 的情况,在 search.php 中加个 $_GET["search"] 的判断,如果传过来 search 就出 json 没传的话直接输出模板原来的内容
    勿喷qwq

    1. 友人C
      @尚寂新

      我现在差不多就是这个思路,只是没用到search.php 这个文件,而另写了一个接口 来ajax请求数据

  10. 心灵博客

    生成文件太大了,我还是老老实实用官方默认的吧。

  11. Eltrac

    感觉 8 错,其实我也想过把 ExSearch 把到我主题上来着

发表评论