基于 sitemap 的搜索

392 阅读2分钟

Pretty Pretty Cooooool Search

功能分析

在较复杂的联想搜索中,想要实现这个功能,并让用户体验流畅,你可能需要一个响应非常的服务端,还需要一套完善的缓存架构。

但对于个站来讲,大部分都是云主机,再加上个人能力有限,很难 hold 住这种架构及场景需求。

拿我的个站来讲,文章篇数不过百,服务器 1G1核1MB,整那么些,费力还不讨好。

一、数据源:

大部分个站中都会加上 RSS,它实质上是一个 XML 类型的数据,使用 Javascript 我们可以将其转换为 JSON 数据格式,这样一来,我们便可以获取到用于搜索的数据源。

二、数据缓存:

RSS 通常由服务端响应一个 sitemap.xml,因此通常是 GET 请求,那么浏览器作为客户端,自然会为我们做一次缓存,就和缓存 *.css*.js 等那些静态资源文件类似。

三、搜索筛选:

这部分只需要让 Javascript 动态获取 input 中的输入值,再去数据源中筛选出匹配的数据,最后动态改变用于显示搜索结果容器中的 innerHTML 即可。

四、总结:

1. 首先,客户端 GET 请求一个 sitemap.xml;

2. 接下来客户端会缓存它;

3. 使用 Javascript 将 sitemap.xml 转换为 JSON 格式;

4. 实时获取 input 值,并在 JSON 数据源中筛选匹配的数据;

5. 将匹配的数据动态渲染至 HTML 中。

Let's do it!laugh

生成 sitemap.xml

我的个站服务端为 Django-1.11,当然其他的 framework 也应该都有自己实现 sitemap.xml 的方法。拿我的个站举例:

1. 创建 feed.py

2. 定义 url

轻松愉快,2步搞定,访问一下我个站的 sitemap 吧:www.lovchun.com/sitemap.xml

客户端请求 sitemap.xml

这一步需要使用 XMLHttpRequest,当然你如果使用 jQuery,也可以用 $.get()

var xmlhttp = new XMLHttpRequest();
var posts;
xmlhttp.open("GET", "/sitemap.xml");
xmlhttp.onreadystatechange = function () {
    if (xmlhttp.readyState != 4) return;
    if (xmlhttp.status != 200 && xmlhttp.status != 304) { return; }
    var node = (new DOMParser).parseFromString(xmlhttp.responseText, 'text/xml');
    node = node.children[0];
   // 在这一步将 XML 转换为 JSON
    posts = getPostsFromXml(node);
}
xmlhttp.send();

XML TO JSON

我使用的是该工具函数:

davidwalsh.name/convert-xml…

实时获取 input 值

监听 onInputChange 事件,即可实时获取到输入框的值:

var searchInputEl = document.querySelector('#js-search__input');
searchInputEl.addEventListener('input', function onInputChange() {
    console.log(this.value);
}

筛选并返回匹配项

我使用的是 fuse.js:fusejs.io,这个 package 作用便是根据你自定义的属性(key),来返回匹配项(obj)。