2012-01-02 42 views
5

Mi piacerebbe sapere come ordinare in modo efficiente in Rails. Sappiamo tutti che si può fare semplice ordinazione in Rails con i seguenti metodi:Ordinamento personalizzato, efficiente, complesso in Rails 3

Model.order("created_at ASC").limit(10) 

In questo caso sto solo tirando le prime 10 voci. Se volessi aggiungere un ordinamento delimitato non temporale, potrei creare una colonna nel modello (ad es. Colonna custom_ordering) e inserire valori per ordinare gli oggetti. In questo caso si dovrebbe semplicemente modificare l'ordine ("custom_ordering ASC") chiamata.

MA supponiamo di voler ordinare in base alle preferenze previste dall'utente. In questo caso, non è possibile creare una nuova colonna perché ogni utente ha gusti diversi. Quale sarebbe un modo intelligente ed efficiente per svolgere questo compito?

Un metodo potrebbe essere quello di creare un algoritmo per prevedere la valutazione di un utente di un oggetto dal modello chiamato model_rating (oggetto). Questo algoritmo sputerebbe un valore intero positivo della loro valutazione. Se percorrevo questa strada, come potrei ordinare in modo efficiente il Modello?

Un altro metodo sarebbe impostare l'algoritmo come model_entry.user_preference (utente). Quindi ho potuto ordinare:

Model.all.sort! { |b, a| a.user_preference(user) <=> b.user_preference(user) } 

Ma questo mi sembra inefficiente. Deve chiamare tutte le voci nel modello e poi ordinarle che, anche se si usano metodi di ordinamento efficienti come l'unione o l'ordinamento a bolle, ottengono scarse prestazioni su modelli con un numero elevato di voci.

Ci sono altri percorsi che non sto considerando? Qualcuno può indicarmi la giusta direzione qui?

risposta

0

In questa soluzione presumo che il calcolo dell'ordine preferito dell'utente sia costoso e che il set che si sta ordinando non si aggiorni spesso.

Quello che si potrebbe fare è calcolare l'ordine ogni tanto (in un'attività in background) e memorizzare l'ordine calcolato in una tabella separata per utente.

In alternativa, se non si dispone di molti utenti, è possibile salvare in una tabella separata il punteggio di ciascun modello per utente e ordinare in base a quel valore in un join. Questi valori possono anche essere ricalcolati su base regolare.

+0

sì, queste sembrano opzioni valide. Pensi che uno di questi approcci sarebbe come un grande sito come Facebook ordina un newsfeed? In questi casi, si hanno sia molte voci della tabella sia molti utenti. – jay

+0

Nel caso di Facebook, penso che memorizzino un newsfeed separato per persona. Non credo che le "storie" siano condivise tra le persone. Queste storie utilizzano risorse condivise (album, commenti, ecc ...) ma ogni storia sulla tua cronologia è costruita per te. (Almeno, è così che lo costruirò) –

+0

beh, molto interessante! sempre illuminante per discutere questa roba con gli altri! grazie mille per il tuo input – jay

0

Bubble sort non è efficiente.

Se si sta parlando di ordinare un singolo modello, allora è vero che tutti gli input di ordinamento sarebbero attributi di quel modello. Se ciascun utente può specificare la propria preferenza di ordinamento, si tratta di un attributo o di un elenco di attributi. Salva quell'elenco come preferenza utente, quindi costruisci dinamicamente la query. Diamine, salva il codice effettivo come preferenza e fai una valutazione su di esso.

Tuttavia, anche l'SQL efficiente si interrompe quando il numero di record si avvicina a una soglia. In tal caso, è necessario un nuovo strumento.

È possibile utilizzare un'implementazione di ricerca corretta, che include intrinsecamente l'ordinamento. Uso Solr con la gemma Sunspot. E sembra che anche Sfinge con la gemma del pensiero-sfinge abbia una buona trazione.