2015-03-29 13 views
5

Mam modelu butów tak:Filtr Sqlalchemy według pola na liście, ale zachowaj oryginalne zamówienie?

class Shoe(db.Model): 
id = db.Column(db.Integer, primary_key = True) 
asin = db.Column(db.String(20), index = True) 

Mam listę identyfikatorów jak IDS = [2,1,3] i kiedy kwerendy na modelu butów takie, że wyniki mają identyfikatory w ' Lista ids, chcę z powrotem: [{id: 2, asin: "111"}, {id: 1, asin: "113"}, {id: 3, asin: "42"}], ale problem jest że użycie następującej instrukcji zapytania nie zachowuje pierwotnej kolejności, wyniki będą wracać losowo. Jak zachować porządek listy, którą filtrowałem?

Nieprawidłowy jeden: Shoe.query.filter(Shoe.id.in_(my_list_of_ids)).all()

+0

myślę, że to jest dość dużo związanych z: http://stackoverflow.com/questions/7443243/sqlalchemy-order-by-field – alecxe

+0

ta nie działa z kolby-SQLAlchemy – user1835351

+0

Dlaczego by nawet chcesz coś takiego zrobić: – adarsh

Odpowiedz

5

Jeśli masz wystarczającą małą listę identyfikatorów, można po prostu wykonywanie zapytań SQL na każdym indywidualnie ID:

[Shoe.query.filter_by(id=id).one() for id in my_list_of_ids] 

Dla dużej liczby identyfikatorów, zapytań SQL będzie trwać długo. Wtedy jesteś lepiej z jednym zapytaniu i wprowadzenie wartości w prawidłowej kolejności, w drugim etapie (zapożyczone z how to select an object from a list of objects by its attribute in python):

shoes = Shoe.query.filter(Shoe.id.in_(my_list_of_ids)).all() 
[next(s for s in shoes if s.id == id) for id in my_list_of_ids] 

to zakładając id są unikatowe (które powinny być w danym przypadku) . Pierwsza metoda spowoduje zgłoszenie wyjątku, jeśli istnieje wiele elementów o tym samym identyfikatorze.

-1

Co masz na myśli mówiąc „pierwotny porządek”? Baza danych nie ma czegoś takiego jak "oryginalna kolejność". Jeśli potrzebujesz jakiś porządek, trzeba dodać coś takiego:

.order_by(Shoe.id.desc()) 

Jeśli nie określić kolejność, to wciąż możliwe, że masz uporządkowane dane z bazy danych. Ale w tym przypadku baza danych po prostu używa porządku, który nie wymaga żadnej niepotrzebnej manipulacji danymi. Wygląda jak uporządkowane dane, ale tak nie jest.

0

Też mam ten sam problem z wykorzystaniem bazy danych MySQL. To, co zrobiłem:

my_list = [13,14,5,6,7] 
# convert my_list to str 
my_list_str = ','.join(map(str, my_list)) 

A oto jak wygląda moje zapytanie:

checkpoints = (
    db_session.query(Checkpoint) 
    .filter(Checkpoint.id.in_(my_list)) 
    .order_by('FIELD(id, ' + my_list_str + ')') 
    .all() 
) 

polu() jest natywna funkcja w MySQL.

EDIT: Więc zapytanie powinno wyglądać następująco:

my_list_of_ids_str = ','.join(map(str, my_list_of_ids)) 
Shoe.query.filter(Shoe.id.in_(my_list_of_ids)).order_by('FIELD(id, ' + my_list_of_ids_str + ')').all() 

Cheers

3

jeden sposób mam rozwiązać ten problem w przeszłości jest za pomocą SQL CASE expression powiedzieć bazę w jakiej kolejności mam lubią wiersze zwrócone. Korzystanie przykład:

from sqlalchemy.sql.expression import case 

ordering = case(
    {id: index for index, id in enumerate(my_list_of_ids)}, 
    value=Shoe.id 
) 
Shoe.query.filter(Shoe.id.in_(my_list_of_ids)).order_by(ordering).all() 
Powiązane problemy