我正在尝试使用Ruby,ActiveRecord和MySQL在引号数据库中完成多字搜索。我的方式如下所示,它正在发挥作用,但我想知道是否有更好的方法。
# receives a string, splits it in a array of words, create the 'conditions'
# query, and send it to ActiveRecord
def search
query = params[:query].strip.split if params[:query]
like = "quote LIKE "
conditions = ""
query.each do |word|
conditions += (like + "'%#{word}%'")
conditions += " AND " unless query.last == word
end
@quotes = Quote.all(:conditions => conditions)
end
我想知道是否有更好的方法来组成这个'条件'字符串。我也尝试使用字符串插值,例如,使用*运算符,但最终需要更多的字符串处理。提前致谢
答案 0 :(得分:9)
首先,我强烈建议您将模型的逻辑转移到模型中。不是在Controller中创建搜索逻辑,而是在Quote模式中创建一个#search方法。
class Quote
def self.search(query)
...
end
end
并且您的控制器变为
# receives a string, splits it in a array of words, create the 'conditions'
# query, and send it to ActiveRecord
def search
@quotes = Quote.search(params[:query])
end
现在,回到原来的问题。您现有的搜索逻辑会犯一个非常糟糕的错误:它直接插入值,将代码打开到SQL注入。假设您使用Rails 3,您可以利用新的#where语法。
class Quote
def self.search(query)
words = query.to_s.strip.split
words.inject(scoped) do |combined_scope, word|
combined_scope.where("quote LIKE ?", "%#{word}%")
end
end
end
这是一个高级主题。我想了解combined_scope
+ inject
的作用,建议您阅读文章The Skinny on Scopes。
答案 1 :(得分:3)
MySQL全文搜索不起作用,所以最好的方法是这样做:
class Quote
def self.search_by_quote(query)
words = query.to_s.strip.split
words.map! { |word| "quote LIKE '%#{word}%'" }
sql = words.join(" AND ")
self.where(sql)
end
end
答案 2 :(得分:1)
答案 3 :(得分:0)
在MySQL中创建一个FULLTEXT索引。有了它,你可以将字符串处理留给MySQL。
示例:http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html