开发者

Multiple word searching with Ruby, and MySQL

I'm trying to accomplish a multiple word searching in a quotes database using Ruby, ActiveRecord, and MySQL. The way I did is shown bellow, and it is working, but I would like to know if there a better way to do.

# 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

I would like to know if there is better way to compose this 'conditions' string. I also tried it using string interpolation, e.g., using the 开发者_如何学运维* operator, but ended up needing more string processing. Thanks in advance


First, I strongly encourage you to move Model's logic into Models. Instead of creating the search logic into the Controller, create a #search method into your Quote mode.

class Quote
  def self.search(query)
    ...
  end
end

and your controller becomes

# 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

Now, back to the original problem. Your existing search logic does a very bad mistake: it directly interpolates value opening your code to SQL injection. Assuming you use Rails 3 you can take advantage of the new #where syntax.

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

It's a little bit of advanced topic. I you want to understand what the combined_scope + inject does, I recommend you to read the article The Skinny on Scopes.


MySQL fulltext search not working, so best way to do this:

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


The better way to do it would be to implement full text searching. You can do this in MySQL but I would highly recommend Solr. There are many resources online for implementing Solr within rails but I would recommend Sunspot as an entrance point.


Create a FULLTEXT index in MySQL. With that, you can leave string processing to MySQL.

Example : http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜