2014-06-20 25 views
5

Sto implementando un sistema di ricerca che utilizza nome, tag e posizione. Esiste una relazione has_and_belongs_to_many tra Server e Tag. Ecco ciò che il mio metodo di ricerca attualmente si presenta come:ActiveRecord has_and_belongs_to_many: trova i modelli con tutti gli elementi specificati

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 

Il parametro tag è solo un elenco separato da virgole di ID. La mia domanda è riportata in un commento nel blocco condizionale if params[:tags]. Come posso eliminare i server che non hanno i tag specificati?

Domanda bonus: un modo per accelerare? Tutti i campi sono facoltativi e utilizzo Postgres esclusivamente.

EDIT

ho trovato un modo per fare questo, ma ho ragione di credere che sarà estremamente lento a correre. C'è un modo più veloce di quello che ho fatto? Forse un modo per fare funzionare il database?

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

Come i tag sono correlati ai server, intendo l'associazione? –

+0

Entrambi hanno has_and_belongs_to_many e utilizzano una tabella di join denominata servers_tags. –

+0

Per "eliminare" intendi distruggere (cioè rimuovere dal database)? –

risposta

5

Recuperare i server con tutte le variabili date con

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 

La parte group(...).having(...) seleziona i server con tutti tag richiesti. Se stai cercando server che hanno uno almeno, rimuovilo.

Con questa soluzione, la ricerca viene eseguita in un'unica richiesta SQL, quindi sarà migliore della soluzione.

+0

Purtroppo questo non funziona correttamente. Non restituisce alcun server anche se ci sono server con il tag. –

Problemi correlati