12/08/2018, 15:12

tìm kiếm và autocomplete trong rails

Tìm kiếm là một trong những tinhsnawng phổ biến nhất được tìm thấy trên bất kể trang web nào. Hiện nay, có rất nhiều giải pháp cho phép bạn dễ dàng tích hợp tìm kiếm vào ứng dụng của bạn, nhưng trong bài này tôi sẽ thảo luận về tìm kiếm của Postgres trong các ứng dụng rails được cung cấp bởi gem ...

Tìm kiếm là một trong những tinhsnawng phổ biến nhất được tìm thấy trên bất kể trang web nào. Hiện nay, có rất nhiều giải pháp cho phép bạn dễ dàng tích hợp tìm kiếm vào ứng dụng của bạn, nhưng trong bài này tôi sẽ thảo luận về tìm kiếm của Postgres trong các ứng dụng rails được cung cấp bởi gem pg_search. Và trên hết, tôi sẽ chỉ cho bạn cách thêm tính năng autocomplete với sự trợ giúp của plugin select2.

chúng ta sẽ tìm hiểu thông qua ba ví dụ về việc sử dụng tính năng tìm kiếm và autocomplete trong rails. Cụ thể, chúng ta sẽ đề cập tới các phần mục sau:

  • Xây dựng tính năng tìm kiếm cơ bản
  • Thảo luận về các tùy chọn bổ sung được hỗ trợ bởi pg_search
  • Xây dựng chức năng autocomplate để hiển thị tên người dùng phù hợp
  • Sử dụng dịch vụ của bên thứ 3 để truy vấn các vị trí địa lý dựa trên đầu vào của người dùng và kích hoạt đồng thời với tính năng autocomplete

mã nguồn có thể tìm thấy tại GitHub.

Đầu tiên chúng ta sẽ tạo ra một ứng dụng rails. Tôi sẽ sử dụng Rails 5.0.1, nhưng hầu hết các khái niệm được giải thích trong bài viết này cũng áp dụng cho các phiên bản thấp hơn. Miên là chúng ta sẽ sử dụng tìm kiếm của Postgres, ứng dụng cần được khởi tạo với cơ sở dữ liệu PostgreSQL:

rails new Autocomplete --database=postgresql

Tạo một cơ sở dữ liệu PG mới và thiết lập cấu hình / database.yml đúng. Để loại trừ username và password của PostGres của tôi. tôi sử dụng gem dotenv-rails

Gemfile

# ...
group :development do
  gem 'dotenv-rails'
end

chạy lệnh cài đặt:

$ bundle install

Khởi tạo file trong project: .env

PG_USER: 'user'
PG_PASS: 'password'

Loại trừ tệp này khỏi bị control: .gitignore

.env

Bạn có thể cấu hình cơ sử dữ liệu như sau:

development:
  adapter: postgresql
  database: autocomplete
  host: localhost
  user: < %= ENV['PG_USER'] %>
  password: < %= ENV['PG_PASS'] %>

Bây giờ, chúng ta hay tạo một bảng và điền dữ liệu mẫu vào đó. Tôi sẽ tạo một bảng user đơn giản chỉ với 2 trường là namsurname

$ rails g model User name:string surname:string
$ rails db:migrate

Sau đó ta dùng gem Faker để tạo dữ liệu mẫu: Gemfile

# ...
group :development do
  gem 'faker'
end

chạy lệnh:

$ bundle install

chúng ta sửa tệp seed để tạo ra 50 user với tên và họ ngẫu nhiên: db/seeds.rb

50.times do
  User.create({name: Faker::Name.first_name,
              surname: Faker::Name.last_name})
end

chạy command:

$ rails db:seed

Cuối cùng, chúng ta viết routes link đến một trang hiển thị toàn bộ user: config/routes.rb

# ...
resources :users, only: [:index]
root to: 'users#index'

usercontroller.rb

class UsersController < ApplicationController
  def index
    @users = User.all
  end
end

views/users/index.html.erb

<ul>
  < %= render @users %>
</ul>

views/users/_user.html.erb

<li>
  < %= user.name %> < %= user.surname %>
</li>

Vậy là chúng ta đã chuẩn bị xong

Bây giờ, chúng ta có thể tiển hành phần tiếp theo và thêm một tính năng tìm kiếm vào ứng dụng.

Những gì tôi mong muốn là làm hiển thị một trường tìm kiếm ở trên cùng của trang gốc và có placeholder là "Enter user's name or surname" cùng với nút "Search!". Khi mẫu được gửi, chỉ những người dùng phù hợp với cụm từ nhập sẽ được hiển thị.

Chúng ta sẽ làm form trước:

views/users/index.html.erb

< %= form_tag users_path, method: :get do %>
  < %= text_field_tag 'term', params[:term], placeholder: "Enter user's name or surname" %>
  < %= submit_tag 'Search!' %>
< % end %>

Bây giờ, chúng ta cần lấy cụm từ được nhập và thực hiện việc tìm kiếm với gem pg_search: Gemfile

# ...
gem 'pg_search'

chạy lệnh cài đặt:

$ bundle install

Gem pg_search hỗ trợ hai chế độ: multisearchable và pg_search_scope. Trong bài viết này, tối sẽ sử dụng tùy chọn thứ 2 (multisearchable hỗ trợ các tùy chọn tương tự, nhưng cho phép tim fkieesm toàn cậu nên được sử dụng trên nhiều mô hình). Ý tưởng khá đơn giản: chúng ta tạo một phạm vi tìm kiếm tương tự như các phạm vi ActiveRecord. Nó có một tên và một loạt các lực chọn, như những lĩnh vực để thực hiện tìm kiếm chống lại. Trước khi làm điều đó, module PgSearch phải được include vào trong model:

models/user.rb

# ...
include PgSearch
pg_search_scope :search_by_full_name, against: [:name, :surname]

trong ví dụ này, chúng ta sử dụng hai trường là :name:surname để thực hiện tìm kiếm Bây giờ, chúng ta sẽ chỉnh sử controller để sử dụng công cụ tìm kiếm mới: users_controller.rb

# ...
if params[:term]
  @users = User.search_by_full_name(params[:term])
else
  @users = User.all
end

Cái hay nhát là nó không đòi hỏi bất kì thay đổi hay bổ sung nào. Bây giờ, bạn có thể khởi động lại Server, truy cập trang và nhập thử tên hoặc hộ của một số người dùng.

Tùy chọn bổ sung

Công việc tìm kiếm không được thuận tiện cho lắm, Ví dụ: nếu tôi chỉ nhập một phần tên hoặc họ, nó sẽ không trả lại bất kì kết quả nào. Điều này có thể dễ dàng sửa chữa bằng cách cung cấp các thông số bổ sung. Trước hết, bạn cần phải chọn kỹ thuật tìm kiếm để sử dụng. Một mặc định là tìm kiếm toàn văn của Postgres, mà tôi sẽ sử dụng trong bài báo này. Hai loại khác là tìm kiếm kiểu trigram và metaphone, yêu cầu phải cài đặt phàn mở rộng PG bổ sung. Để thiết lập thông số kỹ thuật, sử dụng tùy chọn :using :

pg_search_scope :search_by_full_name, against: [:name, :surname], using: [:tsearch]

Mỗi kỹ thuật cũng chấp nhận các lựa chọn khác nhau. Ví dụ: hãy để cho phép tìm kiếm một phần từ ngữ: models/user.rb

class User < ApplicationRecord
  include PgSearch
  pg_search_scope :search_by_full_name, against: [:name, :surname],
    using: {
      tsearch: {
        prefix: true
      }
    }

Bây giờ, nếu bạn nhập "jay" làm cụm từ tìm kiếm, bạn sẽ thấy tất cả người dụng có tên đầy đủ chưa "jay". Lưu ý rằng tính năng này chỉ hỗ trợ bắt đầu từ phiên bản 8.4 của Postgres.

Ngoài ra có một lựa chọn thú vị là :negation, nó cho phép tiêu chuẩn loại trừ được cung cấp bằng cách thêm vào ký hiệu !. Ví dụ: Bob !Jones . Cho phép tùy chọn như sau: models/user.rb

class User < ApplicationRecord
  include PgSearch
  pg_search_scope :search_by_full_name, against: [:name, :surname],
    using: {
      tsearch: {
        prefix: true,
        negation: true
      }
    }

Lưu ý rằng, tính răng này đôi lúc mang lại kết quả không như mong muốn. ngoài ra, nó còn cung cấp tính năng highlight với :highlight option: models/user.rb

# ...
include PgSearch
pg_search_scope :search_by_full_name, against: [:name, :surname],
  using: {
    tsearch: {
      prefix: true,
      negation: true,
      highlight: {
        start_sel: '<b>',
        stop_sel: ',
      }
    }
  }

Ở đây, chúng tôi đang nói rằng, lựa chọn trên được bọc bằng các thẻ b. Tính nawgn nổi bật có mộtt số tùy chọn khác khả dụng

Để tính năng làm nổi bật hoạt động, chúng ta cần phải thực hiện hai thay đổi. Đầu tiên, nối chuỗi phương thức with_pg_search_highlight như sau: users_controller.rb

# ...
@users = User.search_by_full_name(params[:term]).with_pg_search_highlight

bước tiếp theo: views/users/_user.html.erb

<li>
  < % if user.respond_to?(:pg_search_highlight) %>
    < %= user.pg_search_highlight.html_safe %>
  < % else %>
    < %= user.name %> < %= user.surname %>
  < % end %>
</li>

Phương thức pg_search_highlight trả về các giá trị được nối vào các trường tìm kiếm của chúng ta :name:surname và làm highlight kết quả tìm thấy

trên đây là cách sử dụng gem pg_search trong ứng dụng của rails trong bài sau, tôi sẽ làm về phần còn lại autocomplete, rất mong nhận được sự góp ý của mọi người

0