2014-06-20 8 views
5

Wdrażam system wyszukiwania, który używa nazwy, tagów i lokalizacji. Istnieje relacja has_and_belongs_to_many między Server i Tag. Oto, jak wygląda moja metoda wyszukiwania:ActiveRecord has_and_belongs_to_many: znajdź modele z wszystkimi podanymi elementami

def self.search(params) 
    @servers = Server.all 

    if params[:name] 
    @servers = @servers.where "name ILIKE ?", "%#{params[:name]}%" 
    end 

    if params[:tags] 
    @tags = Tag.find params[:tags].split(",") 
    # How do I eliminate servers that do not have these tags? 
    end 

    # TODO: Eliminate those that do not have the location specified in params. 
end 

Parametr tags jest po prostu oddzieloną przecinkami listą identyfikatorów. Moje pytanie znajduje się w komentarzu w bloku warunkowym if params[:tags]. Jak mogę wyeliminować serwery, które nie mają określonych znaczników?

Dodatkowe pytanie: jakikolwiek sposób przyspieszyć? Wszystkie pola są opcjonalne i używam wyłącznie PostgreSQL.

EDIT

znalazłem sposób, aby to zrobić, ale mam powody, aby sądzić, to będzie bardzo powolne uruchomić. Czy jest jakiś sposób, który jest szybszy niż to, co zrobiłem? Być może sposób, aby baza danych wykonała pracę?

tags = Tag.find tokens 
servers = servers.reject do |server| 
    missing_a_tag = false 

    tags.each do |tag| 
     if server.tags.find_by_id(tag.id).nil? 
      missing_a_tag = true 
     end 
    end 

    missing_a_tag 
end 
+0

Jak tagi są powiązane z serwerami, mam na myśli stowarzyszenie? –

+0

Oba mają has_and_belongs_to_many i używają tabeli join o nazwie servers_tags. –

+0

Przez "wyeliminowanie" rozumiesz zniszczenie (czyli usunięcie z bazy danych)? –

Odpowiedz

5

Odzyskaj serwery ze wszystkimi podanymi tagów z

if params[:tags] 
    tags_ids = params[:tags].split(',') 
    @tags = Tag.find(tags_ids) 
    @servers = @servers.joins(:tags).where(tags: {id: tags_ids}).group('servers.id').having("count(*) = #{tags_ids.count}") 
end 

group(...).having(...) część wybiera serwery z wszystkich wymaganych tagów. Jeśli szukasz serwerów, które mają co najmniej, usuń je.

Dzięki temu rozwiązaniu wyszukiwanie odbywa się w jednym żądaniu SQL, więc będzie lepsze niż rozwiązanie.

+0

Niestety to nie działa poprawnie. Nie zwraca żadnych serwerów, nawet jeśli istnieją serwery ze znacznikiem. –

Powiązane problemy