请给我一些帮助。我正在为我的数字图书馆构建高级搜索功能,我想通过书籍的名称或描述来搜索书籍,然后还根据书籍所属的类别过滤搜索结果。
数据库的结构是这样的:书籍属于子类别和类别,而子类别仅属于类别。但是我想按类别过滤。
比方说,我有一本书叫 Great Achievers 和 Great Developers ,它们属于 Achievers 和 Developers 强>分别。我希望搜索以此方式进行:当我使用关键字 Great 进行搜索时,我会看到 Great Achievers 和 Great Developers 这本书,以及何时我按类别成就进行过滤,我只会看到伟大成就者。
现在,我的高级搜索功能可以按图书的名称和描述搜索图书,但不能在搜索结果中按类别过滤图书。
这是图书模型的代码
class Book < ApplicationRecord
has_one_attached :upload
belongs_to :category, required: false
belongs_to :sub_category, required: false
def self.search(keywords)
if keywords
where("name LIKE ? OR description LIKE ? OR author LIKE ?", "%#{keywords}%", "%#{keywords}%", "%#{keywords}%").order('id DESC')
else
order('id DESC')
end
end
end
这是类别模型的代码
class Category < ApplicationRecord
has_many :sub_categories
has_many :books
end
这是子类别模型的代码
class SubCategory < ApplicationRecord
has_many :books
belongs_to :category, required: false
end
这是图书控制器的截断代码
class BooksController < ApplicationController
def index
@books = Book.search(params[:keywords]).paginate(:page => params[:page], :per_page => 9).order('created_at DESC')
end
private
def set_book
@book = Book.find(params[:id])
end
def book_params
params.require(:book).permit(:name, :author, :description, :category_id, :sub_category_id, :new_sub_category_name, :upload, :keywords, :deep_keywords)
end
end
这是图书索引视图上搜索功能的截断代码
<%= form_tag(books_path, method: :get) do %>
<%= text_field_tag :keywords, params[:keywords] %>
<%= collection_select :category, :id, Category.all.order('name ASC'), :id, :name,{include_blank: 'Select Category'} %>
<%= submit_tag 'Search', name: nil %>
<% end %>
请提供任何形式的帮助,我们将不胜感激。谢谢。
答案 0 :(得分:1)
最好的办法是找到过滤器类别下的书籍。然后根据搜索词从该藏书中进行过滤。
您可以按以下方式修改图书控制器代码。
def index
if params['category'].blank? or params['category']['id'].blank?
@books = Book.all
else
category = Category.find(params['category']['id'])
@books = category.books
end
@books = @books.search(params[:keywords]).paginate(:page => params[:page], :per_page => 9).order('created_at DESC')
end
图书索引视图上搜索功能的截断代码可以保持不变
<%= form_tag(books_path, method: :get) do %>
<%= text_field_tag :keywords, params[:keywords] %>
<%= collection_select :category, :id, Category.all.order('name ASC'), :id, :name,{include_blank: 'Select Category'} %>
<%= submit_tag 'Search', name: nil %>
<% end %>
书籍模型的代码也可以保持不变
class Book < ApplicationRecord
has_one_attached :upload
belongs_to :category, required: false
belongs_to :sub_category, required: false
def self.search(keywords)
if keywords
where("name LIKE ? OR description LIKE ? OR author LIKE ?", "%#{keywords}%", "%#{keywords}%", "%#{keywords}%").order('id DESC')
else
order('id DESC')
end
end
end
我希望这会有所帮助。
在有帮助的情况下将此答案赞为有用,或在答案下方评论以进一步说明。
答案 1 :(得分:1)
如果您使用ransack,则可以避免自己进行搜索。您甚至可以在控制器中使用单线来实现所需的功能:
def index
@books = Book.all.ransack(params[:q]).results.paginate(:page => params[:page], :per_page => 9)
end
Then in your requests you have to pass the params[:q]
,对图书资源进行任何所需的搜索。即:
#params[:q] for books with category_id == 10
{ "category_id_eq": 10 }
#params[:q] for books with name or description or author matching "search"
{ "name_or_description_or_author_matches": "%search%" }
#params[:q] for books with name or description or author matching "search" and category_id == 10
{ "name_or_description_or_author_matches": "%search%", "category_id_eq": 10 }
#params[:q] for books with name or description or author matching "search" and category_id == 10, ordered by created_at
{ "name_or_description_or_author_matches": "%search%", "category_id_eq": 10, "s": "created_at desc" }
检查available matchers,以便您可以根据需要构建过滤器。
答案 2 :(得分:0)
您需要加入(未经测试,但您知道了):
def self.search(params)
books = where(nil)
keywords = params.dig(:keywords)
if keywords
books = books.where("name LIKE ? OR description LIKE ? OR author LIKE ?",
"%#{keywords}%", "%#{keywords}%", "%#{keywords}%")
end
cat_id = params.dig(:category, :id)
if cat_id
books = books.joins(:category).where(category: {id: cat_id})
end
books.order('id DESC')
end
编辑:
def index
@books = Book.search(params).
paginate(page: params[:page], per_page: 9).
order('created_at DESC') # You already set order on search
end