目的
jekyll で検索機能を実装するため、全文検索エンジンの lunr.js を導入する方法を調べました。
確認バージョン
- jekyll (3.5.2)
- lunr.js (2.2.1)
導入
チュートリアルサイトを参考に lunr を使おうとしたのですが 検索 - Jekyll Tipsに書いてあるコードそのままでは動きませんでした。
search_data.json ファイルの作成
ここはチュートリアル通りです。
---
layout: null
---
{
{% raw >}}
{% for post in site.posts >}}
"{{ post.url | slugify }}": {
"title": "{{ post.title | xml_escape }}",
"url": " {{ post.url | xml_escape }}",
"author": "{{ post.author | xml_escape }}",
"category": "{{ post.category | xml_escape }}"
}
{% unless forloop.last >}},{% endunless >}}
{% endfor >}}
{% endraw >}}
}
search.html ファイルの作成
ここはチュートリアル通りです。
---
layout: default
---
<form action="get" id="site_search">
<label for="search_box">Search</label><input type="text" id="search_box">
<input type="submit" value="search">
</form>
<ul id="results"></ul>
<script src="https://unpkg.com/lunr/lunr.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="/js/search.js"></script>
/js/search.js ファイルの作成
lurn.js で検索の元となるデータを lunr に渡すところと
検索結果を表示するところを修正しました。
全体は下記のようになります。
jQuery(function() {
// Download the data from the JSON file we generated
var data = $.getJSON('/search_data.json');
var result = [];
data.then(function(response) {
result = response;
window.idx = lunr(function () {
this.field('id');
this.field('title', { boost: 10 });
this.field('author');
this.field('category');
var that = this;
$.each(result, function(i, value) {
var row = $.extend({ "id": i }, value)
that.add(row);
});
});
});
// Event when the form is submitted
$("#site_search").on('submit', function(event){
event.preventDefault();
var query = $("#search_box").val(); // Get the value for the text field
var results = idx.search(query); // Get lunr to perform a search
// 検索結果の表示
display_search_results(results); // Hand the results off to be displayed
});
function display_search_results(results) {
var $search_results = $("#search_results");
// Are there any results?
if (results.length) {
$search_results.empty(); // Clear any old results
// Iterate over the results
results.forEach(function(value) {
var item = result[value.ref];
// Build a snippet of HTML for this result
var appendString = '<li><a href="' + item.url + '">' + item.title + '</a></li>';
// Add it to the results
$search_results.append(appendString);
});
} else {
$search_results.html('<li>No results found</li>');
}
}
});
これから
検索の質を高める
日本語での検索、本文の検索について対応していきたいと思います。
下記を使えばできそうです。
データ量が増えるとパフォーマンスが落ちそう
検索の元となっている json データは jekyll に投稿している全記事となるため
当然、記事の投稿数が増えれば json のデータも増えます。
初期読み込み時に json ファイルのデータをダウンロードしているので
パフォーマンスが悪くなる可能性があります。
Web API 化はどうだろうか
パフォーマンスに対応するため、Web API 化する方法を思いつきましたが
検索結果をサーバー側で生成して、表示という作りになりそうでした。
それだと、 lunr.js を使う意味があまりないかもしれません。