使用RoR 3.2,我搜索搜索逗号分隔的关键字;例如“apple,orange”会找到任何包含“apple”或“orange”字样的记录。我希望能够对结果进行排序,以便首先显示包含两个单词的任何记录。例如
搜索“Apple,Orange”会显示记录
“橙片和苹果派”
记录之前
“Apple Juice”
即使首先找到Apple Juice。如何在按字母数字顺序排序之前添加此第一级排序?我想我可以在控制器索引操作中通过设置索引搜索的顺序来首先显示具有“apple”和“orange”的任何记录,然后显示具有“apple”或“orange”的所有其他记录,我只是不知道怎么做这样的事情。
以下是搜索一组逗号分隔值的范围:
scope :by_description, ->(desc=nil) {
if desc.blank?
all
else
terms = desc.split(/\s*,\s*/).map { |t| t.strip }.map { |t| "%#{t}%" }
where( ( ["#{table_name}.description like ?"] * terms.count).join(' or '), *terms )
end
}
我在控制器中调用范围是这样的:
def index
order = sortable_column_order
if params[:drawings].blank?
@drawings = Drawing.paginate page: params[:page], order: order, per_page: 100
else
@search_string = params[:drawings][:description]
@drawings = Drawing.by_description(params[:drawings][:description])\
.by_drawing_number(params[:drawings][:drawing_number])\
.by_item_number(params[:drawings][:item_number])\
.by_pump_model(params[:drawings][:pump_model])\
.by_frame_size(params[:drawings][:frame_size])\
.by_part_type(params[:drawings][:part_type])\
.by_created_before(params[:drawings]['created_before(1i)'], params[:drawings]['created_before(2i)'], params[:drawings]['created_before(3i)'])\
.by_created_after(params[:drawings]['created_after(1i)'], params[:drawings]['created_after(2i)'], params[:drawings]['created_after(3i)'])\
.paginate page: params[:page], order: order, per_page: 100
@drawings = @drawings.sort_data(@search_string)
end
这就是我正在尝试将它放在一起用于排序方法,但它还没有用,我不确定如何正确地拉入搜索结果并使用它们。 (我正在使用handles_sortable_columns gem。)
def sort_data(search_string)
results_array =
search_array = search_string.gsub(/\s+/, "").split(",")
result = []
results_array.each do |string|
every_word = true
one_word = false
search_array.each do |search|
if string.downcase.include? search.downcase
one_word = true
else
every_word = false
end
end
if every_word
result.unshift(string)
elsif one_word
result << string
end
end
return result
end
答案 0 :(得分:1)
我假设您有一个要搜索的输入字符串数组,并以逗号分隔格式在另一个字符串中获取搜索参数。请找到以下代码。
strings = ["Orange slices and apple pie" , "apple juice", "orange juice", "jackfruit juice", "mixed fruit", "apple pie and orange juice"]
search_string = "apple , orange"
search_array = search_string.gsub(/\s+/, "").split(",")
result = []
strings.each do |string|
every_word = true
one_word = false
search_array.each do |search|
if string.downcase.include? search.downcase
one_word = true
else
every_word = false
end
end
if every_word
result.unshift(string)
elsif one_word
result << string
end
end
puts result.inspect
<强>结果强>
["apple pie and orange juice", "Orange slices and apple pie", "apple juice", "orange juice"]
希望它有所帮助: - )
答案 1 :(得分:1)
您可以通过两种不同的方法完成此操作。一个在 Ruby 空间,一个在 SQL 空间。
您可以实现一个继承自String
的新类,并使用<=>
方法搞砸
class FunkyString < String
def initialize(literal, words = [])
@words = words
super(literal)
end
def <=>(other)
if funky_score != other.funky_score
result = other.funky_score <=> funky_score
else
result = super(other) # fallback to classic string sort
end
end
def funky_score
@words.map{ |word| self.include?(word) ? 1 : 0 }.inject(:+)
end
end
所以对于 Saurabh Lodha 提出的字符串:
strings = ["Orange slices and apple pie" , "apple juice", "orange juice",
"jackfruit juice", "mixed fruit", "apple pie and orange juice"]
strings.shuffle.map {|s| FunkyString.new(s, ['apple', 'orange']) }.sort
#=> ["apple pie and orange juice", "Orange slices and apple pie", "apple juice",
# "orange juice", "jackfruit juice", "mixed fruit"]
将此功能集成到drawing
模型的一种方法是
class Drawing < ActiveRecord::Base
def self.my_weird_sort(keywords = [])
sort_by { |record| record.funky_string_field(keywords) }
end
def funky_string_field(keywords = [])
FunkyString.new(string_field, keywords)
end
end
select string_field, IF(string_field LIKE '%apple%', 1, 0) + IF(string_field LIKE '%orange%', 1, 0) AS the_score from test_tab order by the_score desc, string_field asc;
导致:
+-----------------------------+-----------+
| string_field | the_score |
+-----------------------------+-----------+
| apple pie and orange juice | 2 |
| Orange slices and apple pie | 2 |
| apple juice | 1 |
| orange juice | 1 |
| jackfruit juice | 0 |
| mixed fruit | 0 |
+-----------------------------+-----------+
这样可以转移到rails范围,如下所示:
scope :weird_order ->(word_1, word_2) {
select("select string_field, IF(string_field LIKE '%?%', 1, 0) + IF(string_field LIKE '%?%', 1, 0) AS the_score", word_1, word_2).
order("he_score desc, string_field asc")
}
所以你有
@drawings.weird_order("apple", "orange")
***** 更新 ************
对于sql方法中的任意数量的元素,您可以构造查询字符串:
选择string_field,IF(string_field LIKE&#39;%apple%&#39;,1,0)+ IF(string_field LIKE &#39;%orange%&#39;,1,0)AS_score desc,test_tab命令的the_score,string_field asc;
q = "select string_field, "
q += keywords.map{|x| "IF(string_field LIKE '%" + x + "%', 1, 0)"}.join(" + ")
q += AS the_score from test_tab order by the_score desc, string_field asc"
然后执行自定义查询。请记住,如果您遵循该规则,则需要检查sql注射!