jekyll で検索を実装する方法- lunr を使う
jekyll
Published: 2018-07-16

目的

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 を使う意味があまりないかもしれません。

参考