对待生命,不妨大胆一点,因为我们终将失去它

在Rails 8中使用SQLite进行全文搜索

Rails 8中添加了很多SQLite的功能,而且全都是生产可用的级别,比如非常有用的fts, 也就是full-text search,对于中小型应用相当好用,不用再单独起一个服务。
但该功能全网还没有任何教程或者信息,包括rails官方文档也暂时没有更新,所以只能查代码和一个该功能的PR
以下是配置fts的基本步骤,供参考:
场景:给博客应用添加搜索功能,索引标题(title)和内容(content),其中content是rich text类型

  1. 手动创建迁移文件
    bin/rails g migrate CreateVirtualArticleFts
    内容如下:

    class CreateVirtualArticleFts < ActiveRecord::Migration[8.0]
    def change
    create_virtual_table  :article_fts, :fts5, ["content", "title"]
    end
    end
  2. 创建model文件app/models/article_fts.rb
    class ArticleFts < ApplicationRecord
    self.primary_key = "rowid" # 虚拟表只能使用rowid
    end
  3. 创建app/models/concerns/article/full_text_search.rb文件

    module Article::FullTextSearch
    extend ActiveSupport::Concern
    
    included do
    has_one :article_fts, foreign_key: "rowid"
    end
    
    class_methods do
    def full_text_search(input:, limit:)
      where("article_fts.title LIKE ? OR article_fts.content LIKE ?", "%#{input}%", "%#{input}%")
      .joins(:article_fts)
      .limit(limit)
      .distinct
    end
    end
    
    def find_or_create_article_fts
    return if article_fts
    
    sql = ActiveRecord::Base.sanitize_sql_array(
      [
        "INSERT INTO article_fts (rowid, title, content) VALUES (?, ?, ?)",
        id, 
        title || "", 
        content.to_plain_text
      ]
    )
    ActiveRecord::Base.connection.execute(sql)
    end
    end
  4. app/models/article.rb模型中添加导入和回调函数
    include Article::FullTextSearch
    after_save :find_or_create_article_fts
  5. app/controllers/article_controller.rb使用搜索参数
    @per_page = 10
    @articles = if params[:q].present?
          Article.full_text_search(
            input: params[:q],
            limit: @per_page
          )
  6. 添加搜索框的前端代码
    <%= form_tag root_path, method: :get, class: 'search-form' do %>
      <%= search_field_tag :q, params[:q], placeholder: 'Search...' %>
      <%= submit_tag 'Search' %>
    <% end %>

    最后重新db:migrate后就可用了


Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注