Поиск в Ruby on Rails - Как я ищу на каждом вводимом слове а не точная строка?

Я создал приложение блога w/рубин на направляющих, и я пытаюсь реализовать функцию поиска. Приложение блога позволяет, чтобы пользователи отметили сообщения. Теги создаются в их собственной таблице и belong_to :post. Когда тег создается, так запись в таблице тега, где название тега является tag_name и связанный post_id. Теги являются строками.

Я пытаюсь позволить пользователю искать любое слово tag_name в любом порядке. Вот то, что я имею в виду. Позволяет говорят, что конкретное сообщение имеет тег, который является 'контроллером кода Ruby'. В моей текущей функции поиска будет найден тот тег, если пользователь будет искать 'рубин', 'код Ruby', или 'контроллер кода Ruby'. Не будет найдено, вводит ли пользователь в 'рубиновом контроллере'.

По существу то, что я говорю, - то, что я хотел бы, чтобы каждое слово, вводимое в поиск, разыскивалось, не обязательно 'строка', которая вводится в поиск.

Я экспериментировал с обеспечением нескольких текстовых полей, чтобы позволить пользователю вводить в нескольких словах, и также играл вокруг с кодом ниже, но, может казаться, не выполняю вышеупомянутое. Я плохо знаком с рубином и направляющими очень жаль, если бы это - очевидный вопрос и до установки драгоценного камня или плагина, я думал, что проверил бы, чтобы видеть, была ли простая фиксация. Вот мой код:

Посмотреть:/views/tags/index.html.erb

<% form_tag tags_path, :method => 'get' do %>
    <p>
      <%= text_field_tag :search, params[:search], :class => "textfield-search" %>
      <%= submit_tag "Search", :name => nil, :class => "search-button" %>
    </p>
  <% end %>

TagsController

 def index
    @tags = Tag.search(params[:search]).paginate :page => params[:page], :per_page => 5
    @tagsearch = Tag.search(params[:search])
    @tag_counts = Tag.count(:group => :tag_name, 
       :order => 'count_all DESC', :limit => 100)

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @tags }
    end
  end

Модель тега

class Tag < ActiveRecord::Base
  belongs_to :post
  validates_length_of :tag_name, :maximum=>42
  validates_presence_of :tag_name

  def self.search(search)
    if search
      find(:all, :order => "created_at DESC", :conditions => ['tag_name LIKE ?', "%#{search}%"])
    else
      find(:all, :order => "created_at DESC")
    end
  end

end
9
задан bgadoci 23 April 2010 в 03:24
поделиться

4 ответа

Если я правильно понял вашу проблему, вы хотите вернуть строку, если имена тегов для строки совпадают с одним из слов, переданных в строке запроса.

Вы можете переписать свой метод search следующим образом:

def self.search(search)
  all :conditions =>  (search ? { :tag_name => search.split} : [])
end

Если вам нужно частичное соответствие, сделайте следующее:

def self.search(str)
  return [] if str.blank?
  cond_text   = str.split.map{|w| "tag_name LIKE ? "}.join(" OR ")
  cond_values = str.split.map{|w| "%#{w}%"}
  all(:conditions =>  (str ? [cond_text, *cond_values] : []))
end

Edit 1 Если вы хотите пройти множественный поиск strings тогда:

def self.search(*args)
  return [] if args.blank?
  cond_text, cond_values = [], []
  args.each do |str|
    next if str.blank?  
    cond_text << "( %s )" % str.split.map{|w| "tag_name LIKE ? "}.join(" OR ")
    cond_values.concat(str.split.map{|w| "%#{w}%"})
  end
  all :conditions =>  [cond_text.join(" AND "), *cond_values]
end

Теперь вы можете выполнять такие вызовы, как:

Tag.search("Ruby On Rails")

Tag.search("Ruby On Rails", "Houston")

Tag.search("Ruby On Rails", "Houston", "TX")

Tag.search("Ruby On Rails", "Houston", "TX", "Blah")

Tag.search("Ruby On Rails", "Houston", "TX", "Blah", ....) # n parameters

Предостережение:

Поиск с использованием подстановочных знаков LIKE не очень эффективен (поскольку они не используют индекс). Вам следует подумать об использовании Sphinx (через ThinkingSphinx) ИЛИ Solr (через SunSpot), если у вас много данных.

10
ответ дан 4 December 2019 в 21:09
поделиться

Похоже, вам нужен полнотекстовый поиск. Лучшая интеграция поиска на данный момент - с Sphinx и плагином Thinking_Sphinx . Я использовал его в нескольких проектах, и его очень легко настроить.

Вам действительно нужно установить sphinx на свой хост, поэтому, если вы используете общий хост, это может вызвать некоторые проблемы.

Вы также можете использовать полнотекстовый поиск в базе данных MyISAM MySQL, но производительность при этом довольно низкая.

После того, как ваш sphinx установлен, вы просто вставляете то, что хотите проиндексировать, в свою модель и вызываете model.search. Результатом будет список объектов модели. Он также поддерживает will_paginate.

0
ответ дан 4 December 2019 в 21:09
поделиться

Я бы посоветовал взглянуть на Searchlogic , если вы не хотите использовать отдельную полнотекстовую поисковую систему (Ferret, Sphinx и т. Д. ). Он делает простой поиск чрезвычайно простым, хотя вы, возможно, не захотите использовать его в общедоступных местах без тщательного тестирования.

Также проверьте Railscast на нем: http://railscasts.com/episodes/176-searchlogic

0
ответ дан 4 December 2019 в 21:09
поделиться

Вы можете попробовать настроить хорька , или, если вы действительно гнетете, просто используя рельсы, попробуйте следующее:

# Break the search string into words
words = params[:search].blank? ? [] : params[:search].split(' ')

conditions = [[]] # Why this way? You'll know soon
words.each do |word|
  conditions[0] << ["tag_name LIKE ?"]
  conditions << "%#{word}%"
end
conditions[0] = conditions.first.join(" OR ") # Converts condition string to include " OR " easily ;-)

# Proceed to find using `:conditions => conditions` in your find

надеюсь это помогает =)

0
ответ дан 4 December 2019 в 21:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: