Volltextsuche in Rails mit Elasticsearch

WBOY
Freigeben: 2023-08-31 08:41:05
Original
1500 Leute haben es durchsucht

In diesem Artikel zeige ich Ihnen, wie Sie die Volltextsuche mit Ruby on Rails und Elasticsearch implementieren. Heutzutage ist es jeder gewohnt, einen Suchbegriff einzugeben und Vorschläge und hervorgehobene Ergebnisse für den Suchbegriff zu erhalten. Die Autokorrektur ist auch eine nette Funktion, wenn das, wonach Sie suchen, falsch geschrieben ist, wie wir auf Websites wie Google oder Facebook gesehen haben.

Alle diese Funktionen nur mit einer relationalen Datenbank wie MySQL oder Postgres zu erreichen, ist nicht einfach. Deshalb verwenden wir Elasticsearch, eine Datenbank, die speziell für die Suche erstellt und optimiert wurde. Es ist Open Source und basiert auf Apache Lucene.

Eine der besten Funktionen von Elasticsearch ist die Bereitstellung seiner Funktionalität mithilfe einer REST-API. Daher gibt es Bibliotheken, die diese Funktionalität für die meisten Programmiersprachen kapseln.

Einführung in Elasticsearch

Zuvor habe ich erwähnt, dass Elasticsearch wie eine Datenbank zum Suchen ist. Dies ist nützlich, wenn Sie mit einigen seiner Terminologien vertraut sind.

  • Feld: Ein Feld ist wie ein Schlüssel-Wert-Paar. Der Wert kann ein einfacher Wert (Zeichenfolge, Ganzzahl, Datum) oder eine verschachtelte Struktur (z. B. ein Array oder Objekt) sein. Felder ähneln Spalten in Tabellen in relationalen Datenbanken.
  • Dokument: Ein Dokument ist eine Liste von Feldern. Es handelt sich um ein in Elasticsearch gespeichertes JSON-Dokument. Es ist wie eine Zeile in einer Tabelle in einer relationalen Datenbank. Jedes Dokument wird im Index gespeichert und verfügt über einen Typ und eine eindeutige ID.
  • Typen: Typen sind wie Tabellen in einer relationalen Datenbank. Jeder Typ verfügt über eine Liste von Feldern, die für Dokumente dieses Typs angegeben werden können.
  • Index: Der Index entspricht einer relationalen Datenbank. Es enthält mehrere Arten von Definitionen und speichert mehrere Dokumente.

Hier ist zu beachten, dass in Elasticsearch beim Schreiben eines Dokuments in den Index die Dokumentfelder wörtlich analysiert werden, um die Suche einfach und schnell zu machen. Elasticsearch unterstützt auch die Geolokalisierung, sodass Sie nach Dokumenten suchen können, die sich in einer bestimmten Entfernung von einem bestimmten Standort befinden. Genau so implementiert Foursquare die Suche.

Ich möchte erwähnen, dass Elasticsearch auf hohe Skalierbarkeit ausgelegt ist, sodass es einfach ist, Cluster mit mehreren Servern aufzubauen und eine hohe Verfügbarkeit zu gewährleisten, selbst wenn einige Server ausfallen. Ich werde in diesem Artikel nicht näher auf die Planung und Bereitstellung verschiedener Clustertypen eingehen.

Elasticsearch installieren

Wenn Sie Linux verwenden, können Sie Elasticsearch möglicherweise aus einem der Repositorys installieren. Es kann in APT und YUM verwendet werden.

Wenn Sie einen Mac verwenden, können Sie ihn mit Homebrew installieren: brew install elasticsearch. Nach der Installation von Elasticsearch sehen Sie im Terminal eine Liste der zugehörigen Ordner:

Volltextsuche in Rails mit Elasticsearch

Um zu überprüfen, ob die Installation funktioniert, geben Sie elasticsearch 来启动它。然后在终端中运行 curl localhost:9200 in das Terminal ein und Sie sollten etwas Ähnliches wie das Folgende sehen:

Volltextsuche in Rails mit Elasticsearch

Elastic HQ installieren

Elastic HQ ist ein Überwachungs-Plugin, mit dem wir Elasticsearch über den Browser verwalten können, ähnlich wie phpMyAdmin für MySQL. Um es zu installieren, führen Sie einfach Folgendes im Terminal aus:

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

Nach Abschluss der Installation navigieren Sie in Ihrem Browser zu http://localhost:9200/_plugin/hq:

Volltextsuche in Rails mit Elasticsearch

Klicken Sie auf Verbinden und Sie sehen einen Bildschirm mit dem Clusterstatus: p>

Volltextsuche in Rails mit Elasticsearch

Zu diesem Zeitpunkt wurden erwartungsgemäß noch keine Indizes oder Dokumente erstellt, aber wir haben eine lokale Instanz von Elasticsearch installiert und ausgeführt.

Erstellen Sie eine Rails-Anwendung

Ich werde eine sehr einfache Rails-Anwendung erstellen, in der Sie Artikel zu einer Datenbank hinzufügen, damit wir mit Elasticsearch Volltextsuchen darauf durchführen können. Beginnen Sie mit der Erstellung einer neuen Rails-Anwendung:

rails 新的 elasticsearch-rails

Als nächstes verwenden wir Gerüste, um eine neue Artikelressource zu generieren:

rails生成脚手架文章标题:string text:text

Jetzt müssen wir eine neue Root-Route hinzufügen, damit wir die Artikelliste standardmäßig sehen können. Bearbeiten Sie config/routes.rb:

Rails.application.routes.draw do
  root to: 'articles#index'
  resources :articles
end
Nach dem Login kopieren

Öffnen Sie einen Browser, indem Sie den Befehl rake db:migrate 创建数据库。如果您启动 rails server ausführen, navigieren Sie zu localhost:3000 und fügen Sie einige Artikel zur Datenbank hinzu oder laden Sie einfach die Datei db/seeds.rb mit den von mir erstellten Dummy-Daten herunter, damit Sie nicht viel ausgeben müssen Zeit für das Ausfüllen von Formularen.

Suche hinzufügen

Da wir nun unsere kleine Rails-App haben, die die Artikel in der Datenbank enthält, können wir Suchfunktionen hinzufügen. Wir beginnen mit dem Hinzufügen von Verweisen auf zwei offizielle Elasticsearch-Gems:

gem 'elasticsearch-model'
gem 'elasticsearch-rails'
Nach dem Login kopieren

Auf vielen Websites ist es üblich, im oberen Menü aller Seiten ein Textfeld für die Suche zu haben. Deshalb werde ich unter app/views/search/_form.html.erb einen Formularabschnitt erstellen. Wie Sie sehen, sende ich das generierte Formular mit GET, damit es einfach ist, die URL für eine bestimmte Suche zu kopieren und einzufügen.

<%= form_for :term, url: search_path, method: :get do |form| %>
  <p>
    <%= text_field_tag :term, params[:term] %>
    <%= submit_tag "Search", name: nil %>
  </p>
<% end %>
Nach dem Login kopieren

Fügen Sie im Haupt-Website-Layout einen Verweis auf das Formular hinzu. Bearbeiten Sie app/views/layouts/application.html.erb.

<body>
  <%= render 'search/form' %>
  <%= yield %>
</body>
Nach dem Login kopieren

Jetzt benötigen wir auch einen Controller, um die eigentliche Suche durchzuführen und die Ergebnisse anzuzeigen, also führen wir den Befehl rails g 新控制器 Search aus, um ihn zu generieren.

class SearchController < ApplicationController
  def search
    if params[:term].nil?
	  @articles = []
	else
	  @articles = Article.search params[:term]
	end
  end
end
Nach dem Login kopieren

Wie Sie sehen können, rufe ich die Methode search im Article-Modell auf. Wir haben es noch nicht definiert. Wenn wir also an dieser Stelle versuchen, eine Suche durchzuführen, erhalten wir eine Fehlermeldung. Außerdem haben wir die Routen des SearchControllers nicht in der Datei config/routes.rb hinzugefügt, also machen wir Folgendes:

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

  resources :articles
  get "search", to: "search#search"
end
Nach dem Login kopieren

Wenn wir uns die Dokumentation für das Gem 'elasticsearch-rails' ansehen, müssen wir zwei Module in das Modell einbinden, das in Elasticsearch indiziert werden soll, in unserem Fall article.rb.

require 'elasticsearch/model'

class Article < ActiveRecord::Base
  include Elasticsearch::Model
  include Elasticsearch::Model::Callbacks
end
Nach dem Login kopieren

Das erste Modell fügt die Suchmethode ein, die wir im vorherigen Controller verwendet haben. Das zweite Modul ist in ActiveRecord-Rückrufe integriert, um jede Instanz eines Artikels zu indizieren, die wir in der Datenbank speichern, und aktualisiert den Index auch, wenn wir einen Artikel ändern oder aus der Datenbank löschen. Für uns ist also alles transparent.

Wenn Sie zuvor Daten in die Datenbank importiert haben, sind diese Artikel immer noch nicht im Elasticsearch-Index; nur neue werden automatisch indiziert. Daher müssen wir sie manuell indizieren, was beim Starten in Ordnung ist rails console 就很容易。然后我们只需要运行 irb(main) > Article.import.

Volltextsuche in Rails mit Elasticsearch

Jetzt sind wir bereit, die Suchfunktion auszuprobieren. Wenn ich „ruby“ eingebe und auf „Suchen“ klicke, sind hier die Ergebnisse:

Volltextsuche in Rails mit Elasticsearch

Such-Highlight

Auf vielen Websites können Sie sehen, wie die von Ihnen gesuchten Begriffe auf der Suchergebnisseite hervorgehoben werden. Mit Elasticsearch geht das ganz einfach.

Bearbeiten Sie app/models/article.rb und ändern Sie die Standardsuchmethode:

def self.search(query)
  __elasticsearch__.search(
    {
      query: {
        multi_match: {
          query: query,
          fields: ['title', 'text']
        }
      },
      highlight: {
        pre_tags: ['<em>'],
        post_tags: ['</em>'],
        fields: {
          title: {},
          text: {}
        }
      }
    }
  )
end
Nach dem Login kopieren

Standardmäßig wird die search-Methode durch gem „elasticsearch-models“ definiert und stellt das Proxy-Objekt __elasticsearch__ bereit, um auf die Wrapper-Klasse der Elasticsearch-API zuzugreifen. Daher können wir die Standardabfrage mithilfe der in der Dokumentation bereitgestellten Standard-JSON-Optionen ändern.

Die Suchmethode umschließt nun Ergebnisse, die der Abfrage entsprechen, mit dem angegebenen HTML-Tag. Dazu müssen wir auch die Suchergebnisseite aktualisieren, um HTML-Tags sicher darzustellen. Bearbeiten Sie dazu app/views/search/search.html.erb.

<h1>Search Results</h1>

<% if @articles %>
  <ul class="search_results">
    <% @articles.each do |article| %>
      <li>
	    <h3>
	      <%= link_to article.try(:highlight).try(:title) ?
		      article.highlight.title[0].html_safe : article.title,
              controller: "articles", action: "show", id: article._id %>
	    </h3>
	    <% if article.try(:highlight).try(:text) %>
          <% article.highlight.text.each do |snippet| %>
          <p><%= snippet.html_safe %>...</p>
        <% end %>
      <% end %>
    </li>
  <% end %>
</ul>
<% else %>
  <p>Your search did not match any documents.</p>
<% end %>
Nach dem Login kopieren

Fügen Sie CSS-Stile zu app/assets/stylesheets/search.scss für hervorgehobenes Markup hinzu:

.search_results em {
  background-color: yellow;
  font-style: normal;
  font-weight: bold;
}
Nach dem Login kopieren

Versuchen Sie erneut, nach „Rubin“ zu suchen:

Volltextsuche in Rails mit Elasticsearch

Wie Sie sehen, ist das Hervorheben von Suchbegriffen einfach, aber nicht ideal, da wir eine JSON-Abfrage senden müssen und wir, wie in der Elasticsearch-Dokumentation angegeben, keinerlei Abstraktion haben.

Searchkick-Juwel

Das Searchkick-Gem wird von Instacart bereitgestellt und ist eine Abstraktion des offiziellen Elasticsearch-Gems. Ich werde die Hervorhebungsfunktion umgestalten, sodass wir zuerst gem 'searchkick' zur Gem-Datei hinzufügen. Die erste Klasse, die wir ändern müssen, ist das Article.rb-Modell:

class Article < ActiveRecord::Base
  searchkick
end
Nach dem Login kopieren

Wie Sie sehen, ist es viel einfacher. Wir müssen die Artikel erneut indizieren und den Befehl rake searchkick:reindex CLASS=Article ausführen. Um Suchbegriffe hervorzuheben, müssen wir einen zusätzlichen Parameter von search_controller.rb an die Suchmethode übergeben.

class SearchController < ApplicationController
  def search
    if params[:term].nil?
	  @articles = []
	else
	  term = params[:term]
	  @articles = Article.search term, fields: [:text], highlight:  true
	end
  end
end
Nach dem Login kopieren

Die letzte Datei, die wir ändern müssen, ist views/search/search.html.erb , da Searchkick jetzt Ergebnisse in einem anderen Format zurückgibt:

<h2>Search Results for: <i><%= params[:term] %></i></h2>

<% if @articles %>
<ul class="search_results">
  <% @articles.with_details.each do |article, details| %>
    <li>
	  <h3>
	    <%= link_to article.title, controller: "articles", action: "show", id: article.id %>
	  </h3>
      <p><%= details[:highlight][:text].html_safe %>...</p>
	</li>
  <% end %>
</ul>
<% else %>
  <p>Your search did not match any documents.</p>
<% end %>
Nach dem Login kopieren

Jetzt ist es an der Zeit, die App erneut auszuführen und die Suchfunktion zu testen:

Volltextsuche in Rails mit Elasticsearch

请注意,我输入了搜索词“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);
Nach dem Login kopieren

关于前一个片段的一些评论。在最后两行中,因为我没有禁用涡轮链接,所以这是连接我想要在页面加载时运行的代码的方法。在脚本的第一部分,您可以看到我正在使用 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
Nach dem Login kopieren

接下来,我将在 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
Nach dem Login kopieren

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

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

Volltextsuche in Rails mit Elasticsearch

结论

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

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

Das obige ist der detaillierte Inhalt vonVolltextsuche in Rails mit Elasticsearch. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage