>  기사  >  웹 프론트엔드  >  Elasticsearch를 사용하여 Rails에서 전체 텍스트 검색

Elasticsearch를 사용하여 Rails에서 전체 텍스트 검색

WBOY
WBOY원래의
2023-08-31 08:41:051502검색

이 글에서는 Ruby on Rails와 Elasticsearch를 사용하여 전체 텍스트 검색을 구현하는 방법을 보여 드리겠습니다. 요즘에는 모든 사람이 검색어를 입력하고 해당 검색어에 대한 제안과 강조된 결과를 얻는 데 익숙합니다. 자동 수정은 Google이나 Facebook과 같은 사이트에서 볼 수 있듯이 검색하려는 내용의 철자가 틀린 경우에도 유용한 기능입니다.

MySQL이나 Postgres와 같은 관계형 데이터베이스만 사용하여 이러한 모든 기능을 달성하는 것은 간단하지 않습니다. 그래서 우리는 검색을 위해 특별히 구축되고 최적화된 데이터베이스라고 생각할 수 있는 Elasticsearch를 사용합니다. 오픈 소스이며 Apache Lucene을 기반으로 구축되었습니다.

Elasticsearch의 가장 뛰어난 기능 중 하나는 REST API를 사용하여 기능을 노출하는 것이므로 대부분의 프로그래밍 언어에 대해 이 기능을 캡슐화하는 라이브러리가 있습니다.

Elasticsearch 소개

앞서 Elasticsearch는 검색을 위한 데이터베이스와 같다고 말씀드렸는데요. 이는 일부 용어에 익숙하다면 유용할 것입니다.

  • Field: 필드는 키-값 쌍과 같습니다. 값은 단순 값(문자열, 정수, 날짜)이거나 중첩 구조(예: 배열 또는 개체)일 수 있습니다. 필드는 관계형 데이터베이스 테이블의 열과 유사합니다.
  • Document: 문서는 필드 목록입니다. Elasticsearch에 저장된 JSON 문서입니다. 이는 관계형 데이터베이스의 테이블 행과 같습니다. 각 문서는 인덱스에 저장되며 유형과 고유 ID를 갖습니다.
  • 유형: 유형은 관계형 데이터베이스의 테이블과 같습니다. 각 유형에는 해당 유형의 문서에 대해 지정할 수 있는 필드 목록이 있습니다.
  • Index: 인덱스는 관계형 데이터베이스와 동일합니다. 여기에는 여러 유형의 정의가 포함되어 있으며 여러 문서를 저장합니다.

여기서 주목해야 할 점은 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生成脚手架文章标题:string text:text

이제 기본적으로 기사 목록을 볼 수 있도록 새 루트 경로를 추가해야 합니다. config/routes.rb 편집:

으아아아

명령 rake db:migrate 创建数据库。如果您启动 rails server을 실행하여 브라우저를 열고, localhost:3000으로 이동하여 데이터베이스에 일부 기사를 추가하거나, 내가 만든 더미 데이터가 포함된 db/seeds.rb 파일을 다운로드하면 많은 비용을 들이지 않아도 됩니다. 양식을 작성하는 데 시간이 걸립니다.

검색 추가

이제 데이터베이스에 기사가 포함된 작은 Rails 앱이 있으므로 검색 기능을 추가할 준비가 되었습니다. 두 개의 공식 Elasticsearch Gem에 대한 참조를 추가하는 것부터 시작하겠습니다.

으아아아

많은 웹사이트에서는 모든 페이지의 상단 메뉴에 검색용 텍스트 상자가 있는 것이 일반적입니다. 그래서 app/views/search/_form.html.erb에 양식 섹션을 만들겠습니다. 보시다시피 생성된 양식을 GET을 사용하여 전송하므로 특정 검색에 대한 URL을 쉽게 복사하여 붙여넣을 수 있습니다.

으아아아

기본 웹사이트 레이아웃의 양식에 대한 참조를 추가하세요. app/views/layouts/application.html.erb를 편집하세요.

으아아아

이제 실제 검색을 수행하고 결과를 표시하는 컨트롤러도 필요하므로 이를 생성하기 위해 rails g 新控制器 Search 명령을 실행합니다.

으아아아

보시다시피 저는 Article 모델에서 메서드 search를 호출하고 있습니다. 아직 정의하지 않았으므로 이 시점에서 검색을 수행하려고 하면 오류가 발생합니다. 또한 config/routes.rb 파일에 SearchController의 경로를 추가하지 않았으므로 다음을 수행해 보겠습니다.

으아아아

'elasticsearch-rails'에 대한 문서를 보면 Elasticsearch에서 인덱싱할 모델에 두 개의 모듈(우리의 경우 article.rb.

)을 포함해야 합니다. 으아아아

첫 번째 모델은 이전 컨트롤러에서 사용한 검색 방법을 주입합니다. 두 번째 모듈은 ActiveRecord 콜백과 통합되어 데이터베이스에 저장하는 기사의 각 인스턴스를 색인화하고, 데이터베이스에서 기사를 수정하거나 삭제하는 경우에도 색인을 업데이트합니다. 그래서 모든 것이 우리에게 투명합니다.

이전에 데이터를 데이터베이스로 가져온 경우 이러한 기사는 아직 Elasticsearch 색인에 없습니다. 새 기사만 자동으로 색인화됩니다. 따라서 수동으로 색인을 생성해야 하며 rails console 就很容易。然后我们只需要运行 irb(main) > Article.import를 실행해도 괜찮습니다.

Elasticsearch를 사용하여 Rails에서 전체 텍스트 검색

이제 검색 기능을 사용해 볼 준비가 되었습니다. "ruby"를 입력하고 검색을 클릭하면 결과는 다음과 같습니다.

Elasticsearch를 사용하여 Rails에서 전체 텍스트 검색

검색 하이라이트

많은 웹사이트에서는 검색한 용어가 검색 결과 페이지에서 어떻게 강조 표시되는지 확인할 수 있습니다. Elasticsearch를 사용하면 이 작업을 쉽게 수행할 수 있습니다.

편집 app/models/article.rb 및 기본 검색 방법 수정:

으아아아

기본적으로 search 메서드는 gem 'elasticsearch-models'에 의해 정의되며 Elasticsearch API의 래퍼 클래스에 액세스하기 위한 프록시 개체 __elasticsearch__를 제공합니다. 따라서 설명서에서 제공하는 표준 JSON 옵션을 사용하여 기본 쿼리를 수정할 수 있습니다.

이제 검색 방법은 지정된 HTML 태그를 사용하여 쿼리와 일치하는 결과를 래핑합니다. 이를 위해서는 HTML 태그를 안전하게 렌더링하도록 검색 결과 페이지도 업데이트해야 합니다. 이렇게 하려면 app/views/search/search.html.erb를 편집하세요.

으아아아

강조된 마크업을 위해 app/assets/stylesheets/search.scss에 CSS 스타일을 추가하세요.

으아아아

"ruby"를 다시 검색해 보세요:

Elasticsearch를 사용하여 Rails에서 전체 텍스트 검색

보시다시피, 검색어를 강조표시하는 것은 쉽지만 JSON 쿼리를 보내야 하고 Elasticsearch 문서에 명시되어 있듯이 어떤 종류의 추상화가 없기 때문에 이상적이지는 않습니다.

서치킥 보석

Searchkick gem은 Instacart에서 제공하며 공식 Elasticsearch gem을 기반으로 한 추상화입니다. 강조 표시 기능을 리팩터링할 예정이므로 먼저 gemfile에 gem 'searchkick'를 추가합니다. 우리가 변경해야 할 첫 번째 클래스는 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.