2014-07-03 17 views
14

Mam algorytm Pythona, który zwraca kolejność rangowania wierszy bazy danych dla danego użytkownika. Ten algorytm wyświetla listę identyfikatorów kluczy podstawowych (klucze te można połączyć za pomocą post.id). To wygląda jak poniżej, z wyjątkiem, że istnieją potencjalnie tysiące meczów:Kolejność i paginacja w alchemii SQL przy użyciu rankingu innego niż sql

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

chcę pouczać SQLAlchemy wybrać te wiersze, a zamówić je, ponieważ są one uporządkowane na liście. Połów jest, że chciałbym wykonać pagination na tej

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) 

używam PostgreSQL jako bazy danych.

+0

Mam dokładnie ten sam problem. – anvd

+0

którego bazy danych używasz? – van

+1

@van w moim przypadku to postgres. Nie wiem o mgoldwasser – anvd

Odpowiedz

1

O ile nie jest to dobre rozwiązanie, mam zamiar się włamać razem mój własny obiekt podzielony na strony:

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)] 

Myślę, że jedynym sposobem na uporządkowanie jest stworzenie listy wszystkich wyników i sortować je w pyton według niektórych funkcji 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

Myślę, że kolejność jest ważniejsze, bo bez niej stronicowanie poziom bazy danych jest całkowicie bezużyteczne. Zauważyłem, że moja odpowiedź w ogóle nie uwzględnia aspektu stronicowania, ale zakładam, że nawet odpowiedź dostarczona przez @mgoldwasser może być do tego użyta.

Oto, co wymyśliłem, aby móc wybrać niektóre obiekty i zachować ich kolejność zgodnie z początkową listą filtrów. Kod jest wymowne:

# 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 
    ) 

Działa na postgresql i sqlite.

+0

Myślę, że najprostszą metodą jest użycie procesora context_processor, utworzenie podlist listy podzielonych przez całkowity numer strony i uruchomienie dla każdego elementu na liście określonego zapytania filter_by = X. Problemem jest widget paginacji, ale można to zrobić ręcznie. Po prostu podziel wszystkie elementy listy przez sumę stron. W każdym razie, poczekam, aby sprawdzić, czy jest to przyjazne dla środowiska. – anvd