2014-07-03 8 views
14

Ho un algoritmo python che restituisce un ordine di classificazione delle righe del database per un determinato utente. Questo algoritmo genera un elenco di ID chiave primaria (queste chiavi possono essere unite con post.id). Sembra che il seguito, se non che ci sono potenzialmente migliaia di incontri:Ordinamento e impaginazione in alchimia SQL utilizzando il ranking non sql

result_rank = [1286, 1956, 6759, 3485, 2309, 3409, 9023, 912, 13098, 23489, 19023, 1239] 

voglio istruire sqlalchemy per selezionare queste righe, e li ordine in cui sono ordinate nella lista. Il problema è che mi piacerebbe svolgere pagination su questo

results = posts.query().filter(posts.id.in_(
    resultIds)).order_by(??? how can I order by post.id = result_rank ???).paginate(page_num, posts_per_page) 

Sto usando PostgreSQL come database.

+0

Sto avendo esattamente lo stesso problema. – anvd

+0

quale database back-end usi? – van

+1

@van nel mio caso è postgres. Non so su mgoldwasser – anvd

risposta

1

A meno che non ci sia una buona soluzione, ho intenzione di incidere insieme il mio proprio oggetto paginate:

class paginate_obj: 

    """ Pagination dummy object. Takes a list and paginates it similar to sqlalchemy paginate() """ 
    def __init__(self, paginatable, page, per_page): 
     self.has_next = (len(paginatable)/per_page) > page 
     self.has_prev = bool(page - 1) 
     self.next = page + self.has_next 
     self.prev = page - self.has_prev 
     self.items = paginatable[(page-1)*(per_page):(page)*(per_page)] 

Credo che l'unico modo per farlo ordinamento è quello di creare un elenco di tutti i risultati e ordinare in pitone secondo alcuni funzione lambda:

results = my_table.query().all() 
results.sort(key=lamba x: distance(x.lat, x.long, user_lat, user_long) 
paginated_results = paginate_obj(results, 1, 10) #returns the first page of 10 elements 
1

credo che l'ordine è più importante, perché senza di essa l'impaginazione livello di database è completamente inutile. Dopo averlo notato, la mia risposta non copre affatto l'aspetto della paginazione, ma presumo che anche la risposta fornita da @mgoldwasser possa essere utilizzata per questo.

Questo è ciò che mi è venuto in mente per poter selezionare alcuni oggetti e mantenerne l'ordine come da elenco iniziale dei filtri. Il codice si spiega da sé:

# input 
post_ids = [3, 4, 1] 

# create helper (temporary in-query table with two columns: post_id, sort_order) 
# this table looks like this: 
# key | sort_order 
# 3 |   0 
# 4 |   1 
# 1 |   2 
q_subq = "\nUNION ALL\n".join(
    "SELECT {} AS key, {} AS sort_order".format(_id, i) 
    for i, _id in enumerate(post_ids) 
) 

# wrap it in a `Selectable` so that we can use JOINs 
s = (select([literal_column("key", Integer), 
      literal_column("sort_order", Integer)]) 
    .select_from(text("({}) AS helper".format(text(q_subq)))) 
    ).alias("helper") 

# actual query which is both the filter and sorter 
q = (session.query(Post) 
    .join(s, Post.id == s.c.key) # INNER JOIN will filter implicitly 
    .order_by(s.c.sort_order) # apply sort order 
    ) 

Funziona sia postgresql e sqlite.

+0

Penso che il modo più semplice sia usare il context_processor, creare sottodistribuzioni divise per il numero di pagina totale ed eseguire per ogni elemento in elenco una query specifica filter_by = X. Il problema è il widget di impaginazione, ma può essere fatto manualmente. Basta dividere gli elementi totali della lista per il totale della pagina. Ad ogni modo, aspetterò di verificare se c'è un amico di fare questo. – anvd