Elasticsearchを使用したRailsでの全文検索

WBOY
リリース: 2023-08-31 08:41:05
オリジナル
1501 人が閲覧しました

この記事では、Ruby on Rails と Elasticsearch を使用して全文検索を実装する方法を説明します。今日では、誰もが検索語を入力すると、その検索語に対する候補や強調表示された結果が表示されることに慣れています。 Google や Facebook などのサイトで見られるように、オートコレクトは、検索しようとしているもののスペルが間違っている場合にも便利な機能です。

MySQL や Postgres などのリレーショナル データベースだけを使用してこの機能をすべて実現するのは簡単ではありません。そこで、Elasticsearch を使用します。これは、検索専用に構築され最適化されたデータベースと考えることができます。これはオープンソースであり、Apache Lucene 上に構築されています。

Elasticsearch の最も優れた機能の 1 つは、REST API を使用してその機能を公開することです。そのため、ほとんどのプログラミング言語に対してこの機能をカプセル化するライブラリがあります。

Elasticsearch の概要

先ほど、Elasticsearch は検索用のデータベースのようなものであると述べました。これは、いくつかの用語に精通している場合に役立ちます。

  • フィールド: フィールドはキーと値のペアのようなものです。値は、単純な値 (文字列、整数、日付) または入れ子の構造 (配列やオブジェクトなど) にすることができます。フィールドは、リレーショナル データベースのテーブルの列に似ています。
  • Document: ドキュメントはフィールドのリストです。 Elasticsearch に保存されている JSON ドキュメントです。これは、リレーショナル データベースのテーブル内の行のようなものです。各ドキュメントはインデックスに保存され、タイプと一意の ID を持ちます。
  • Type: タイプはリレーショナル データベースのテーブルのようなものです。各タイプには、そのタイプのドキュメントに指定できるフィールドのリストがあります。
  • Index: インデックスはリレーショナル データベースに相当します。複数の種類の定義が含まれており、複数のドキュメントが保存されます。

ここで注意すべき点の 1 つは、Elasticsearch では、ドキュメントをインデックスに書き込むときに、ドキュメントのフィールドが文字通り分析され、検索が簡単かつ高速になるということです。 Elasticsearch は地理位置情報もサポートしているため、特定の場所から一定の距離内にあるドキュメントを検索できます。これはまさに Foursquare が検索を実装する方法です。

Elasticsearch は高いスケーラビリティを念頭に置いて構築されているため、複数のサーバーでクラスターを構築するのが簡単で、一部のサーバーに障害が発生した場合でも高可用性を実現できることを述べておきたいと思います。この記事では、さまざまな種類のクラスターを計画および展開する方法については詳しく説明しません。

Elasticsearchをインストールする

Linux を使用している場合は、いずれかのリポジトリから Elasticsearch をインストールできる場合があります。 APTとYUMで使用できます。

Mac を使用している場合は、Homebrew を使用してインストールできます: brew install elasticsearch。 elasticsearch をインストールすると、ターミナルに関連フォルダーのリストが表示されます:

Elasticsearchを使用したRailsでの全文検索

インストールが適切に動作していることを確認するには、ターミナルに elasticsearch と入力してインストールを開始します。次に、ターミナルで curl localhost:9200 を実行すると、次のような内容が表示されるはずです。

Elasticsearchを使用したRailsでの全文検索

Elastic HQ をインストールする

Elastic HQ は、MySQL の phpMyAdmin と同様に、ブラウザから Elasticsearch を管理するために使用できる監視プラグインです。インストールするには、ターミナルで次を実行するだけです:

/usr/local/Cellar/elasticsearch/2.2.0_1/libexec/bin/plugin -install royrusso/elasticsearch-HQ

インストールが完了したら、ブラウザで http://localhost:9200/_plugin/hq に移動します:

Elasticsearchを使用したRailsでの全文検索

[

Connect] をクリックすると、クラスターのステータスを示す画面が表示されます: p>

Elasticsearchを使用したRailsでの全文検索

この時点では、ご想像のとおり、インデックスやドキュメントはまだ作成されていませんが、Elasticsearch のローカル インスタンスがインストールされ、実行されています。

Rails アプリケーションの作成

ここでは、Elasticsearch を使用して記事の全文検索を実行できるように、記事をデータベースに追加する非常に単純な Rails アプリケーションを作成します。新しい Rails アプリケーションを作成することから始めます:

rails 新しい elasticsearch-rails

次に、スキャフォールディングを使用して新しい記事リソースを生成します:

rails はスキャフォールディング記事のタイトル:文字列テキスト:テキストを生成します

次に、デフォルトで記事リストを表示できるように、新しいルート ルートを追加する必要があります。

config/routes.rb: を編集しますリーリー

コマンド rake db:merge を実行してデータベースを作成します。 rails サーバー を起動する場合は、ブラウザを開いて localhost:3000 に移動し、いくつかの記事をデータベースに追加するか、作成したダミー データを含むファイル db/seeds.rb をダウンロードしてください。フォームに記入するのに多くの時間を費やさなければなりません。

検索を追加

これで、データベース内の記事を含む小さな Rails アプリケーションが完成したので、検索機能を追加する準備が整いました。まず、2 つの公式 Elasticsearch Gem への参照を追加します:

リーリー

多くの Web サイトでは、すべてのページのトップ メニューに検索用のテキスト ボックスがあるのが一般的です。そこで、app/views/search/_form.html.erb にフォーム セクションを作成します。 ご覧のとおり、生成されたフォームを GET を使用して送信しているため、特定の検索の URL を簡単にコピーして貼り付けることができます。

リーリー

メイン サイト レイアウトのフォームへの参照を追加します。 app/views/layouts/application.html.erb を編集します。

リーリー

実際の検索を実行して結果を表示するためのコントローラーも必要なので、コマンド rails g newcontroller Search を実行してコントローラーを生成します。

リーリー

ご覧のとおり、Article モデルでメソッド search を呼び出しています。まだ定義していないため、この時点で検索を実行しようとするとエラーが発生します。また、SearchController のルートを config/routes.rb ファイルに追加していないので、これを追加しましょう:

リーリー

gem 'elasticsearch-rails' のドキュメントを見ると、Elasticsearch でインデックスを作成するモデルに 2 つのモジュール (この場合は article.rb##) を含める必要があります。 #. リーリー

最初のモデルは、前のコントローラーで使用した Search メソッドを挿入します。 2 番目のモジュールは、ActiveRecord コールバックと統合して、データベースに保存する記事の各インスタンスにインデックスを付けます。また、データベースから記事を変更または削除すると、インデックスも更新されます。したがって、それは私たちにとってすべて透明です。

以前にデータをデータベースにインポートした場合、これらの記事はまだ Elasticsearch インデックスに含まれていないため、新しい記事のみが自動的にインデックス付けされます。したがって、手動でインデックスを付ける必要がありますが、

rails console を起動すれば簡単です。次に、irb(main) > Article.import を実行するだけです。

Elasticsearchを使用したRailsでの全文検索

これで、検索機能を試す準備が整いました。 「ruby」と入力して検索をクリックすると、結果は次のようになります:

Elasticsearchを使用したRailsでの全文検索

検索ハイライト

多くの Web サイトでは、検索した用語が検索結果ページでどのように強調表示されているかを確認できます。これは Elasticsearch を使用すると簡単に実行できます。

app/models/article.rbを編集し、デフォルトの検索方法を変更します: リーリー

デフォルトでは、

search メソッドは gem 'elasticsearch-models' によって定義され、Elasticsearch API のラッパー クラスにアクセスするためのプロキシ オブジェクト __elasticsearch__ を提供します。したがって、ドキュメントで提供されている標準の JSON オプションを使用して、デフォルトのクエリを変更できます。

検索メソッドは、クエリに一致する結果を指定された HTML タグでラップするようになりました。これを行うには、HTML タグを安全にレンダリングできるように検索結果ページを更新する必要もあります。これを行うには、

app/views/search/search.html.erb を編集します。 リーリー

強調表示されたタグの CSS スタイルを

app/assets/stylesheets/search.scss に追加します: リーリー

「ruby」をもう一度検索してみてください:

Elasticsearchを使用したRailsでの全文検索

ご覧のとおり、検索語を強調表示するのは簡単ですが、JSON クエリを送信する必要があり、Elasticsearch のドキュメントで指定されているように、いかなる種類の抽象化も行っていないため、理想的ではありません。 。

サーチキックジェム

Searchkick gem は Instacart によって提供され、公式 Elasticsearch gem を抽象化したものです。ハイライト機能をリファクタリングするので、最初に

gem 'searchkick' を gemfile に追加します。変更する必要がある最初のクラスは Article.rb モデルです: リーリー

ご覧のとおり、はるかに簡単です。記事のインデックスを再度再作成し、コマンド

rake searchkick:reindex CLASS=Article を実行する必要があります。検索語を強調表示するには、search_controller.rb から追加のパラメーターを検索メソッドに渡す必要があります。 リーリー

変更する必要がある最後のファイルは

views/search/search.html.erb です。これは、searchkick が別の形式で結果を返すようになったためです。 リーリー

今度は、アプリケーションを再度実行して、検索機能をテストします:

Elasticsearchを使用したRailsでの全文検索

请注意,我输入了搜索词“dato”。我这样做的目的是为了向您展示,默认情况下,searchkick 设置为分析索引的文本,并且更允许拼写错误。

自动建议

自动建议或预先输入可预测用户将输入的内容,从而使搜索体验更快、更轻松。请记住,除非您有数千条记录,否则最好在客户端进行过滤。

让我们首先添加 typeahead 插件,该插件可通过 gem 'bootstrap-typeahead-rails' 获得,并将其添加到您的 Gemfile 中。接下来,我们需要向 app/assets/javascripts/application.js 添加一些 JavaScript,以便当您开始在搜索框中输入内容时,会出现一些建议。

//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require bootstrap-typeahead-rails
//= require_tree .

var ready = function() {
  var engine = new Bloodhound({
      datumTokenizer: function(d) {
          console.log(d);
          return Bloodhound.tokenizers.whitespace(d.title);
      },
      queryTokenizer: Bloodhound.tokenizers.whitespace,
      remote: {
          url: '../search/typeahead/%QUERY'
      }
  });

  var promise = engine.initialize();

  promise
      .done(function() { console.log('success'); })
      .fail(function() { console.log('error') });

  $("#term").typeahead(null, {
    name: "article",
    displayKey: "title",
    source: engine.ttAdapter()
  })
};

$(document).ready(ready);
$(document).on('page:load', ready);
ログイン後にコピー

关于前一个片段的一些评论。在最后两行中,因为我没有禁用涡轮链接,所以这是连接我想要在页面加载时运行的代码的方法。在脚本的第一部分,您可以看到我正在使用 Bloodhound。它是 typeahead.js 建议引擎,我还设置了 JSON 端点来发出 AJAX 请求来获取建议。之后,我在引擎上调用 initialize(),并使用其 id“term”在搜索文本字段上设置预输入。

现在,我们需要对建议进行后端实现,让我们从添加路由开始,编辑 app/config/routes.rb

Rails.application.routes.draw do
  root to: 'articles#index'

  resources :articles
  get "search", to: "search#search"
  get 'search/typeahead/:term' => 'search#typeahead'
end
ログイン後にコピー

接下来,我将在 app/controllers/search_controller.rb 上添加实现。

def typeahead
  render json: Article.search(params[:term], {
    fields: ["title"],
    limit: 10,
    load: false,
    misspellings: {below: 5},
  }).map do |article| { title: article.title, value: article.id } end
end
ログイン後にコピー

此方法返回使用 JSON 输入的术语的搜索结果。我只按标题搜索,但我也可以指定文章的正文。我还将搜索结果的数量限制为最多 10 个。

现在我们准备尝试 typeahead 实现:

Elasticsearchを使用したRailsでの全文検索

结论

如您所见,将 Elasticsearch 与 Rails 结合使用使搜索数据变得非常简单且快速。在这里,我向您展示了如何使用 Elasticsearch 提供的低级 gem,以及 Searchkick gem,这是一个隐藏了 Elasticsearch 工作原理的一些细节的抽象。

根据您的具体需求,您可能会很乐意使用 Searchkick 并快速轻松地实施全文搜索。另一方面,如果您有一些其他复杂的查询,包括过滤器或组,您可能需要了解有关 Elasticsearch 上查询语言的详细信息,并最终使用较低级别的 gem 'elasticsearch-models' 和 'elasticsearch-导轨”。

以上がElasticsearchを使用したRailsでの全文検索の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート