2015-03-29 7 views
5

Ho un modello di scarpe del genere:Sqlalchemy filtra per campo nell'elenco ma mantiene l'ordine originale?

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

Ho un elenco di ID come IDS = [2,1,3] e quando mi interrogo sul modello di scarpa in modo tale che i risultati hanno ids nella ' lista degli id, voglio tornare: [{id: 2, asin: "111"}, {id: 1, asin: "113"}, {id: 3, asin: "42"}] ma il problema è che l'utilizzo della seguente istruzione di query non conserva l'ordine originale, i risultati torneranno casuali. Come mantenere l'ordine della lista filtrata da?

errato uno: Shoe.query.filter(Shoe.id.in_(my_list_of_ids)).all()

+0

Credo che questo è più o meno correlato: http://stackoverflow.com/questions/7443243/sqlalchemy-order-by-field – alecxe

+0

Questo non funziona con la boccetta-sqlalchemy – user1835351

+0

Perché sarebbe vuoi anche fare qualcosa di simile – adarsh

risposta

5

Se si dispone di una ragionevole piccolo elenco di ID, si può solo eseguire query SQL su ogni id singolarmente:

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

Per un gran numero di ID, query SQL prenderanno un lungo periodo di tempo. Poi si sta meglio con una singola query e mettendo i valori nell'ordine corretto in una seconda fase (preso in prestito da 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] 

Questo sta assumendo i id sono uniche (che dovrebbero essere nel tuo caso) . Il primo metodo genererà un'eccezione se ci sono più elementi con lo stesso id.

-1

Che cosa si intende quando si dice "ordine originale"? Il database non ha "ordine originale". Se avete bisogno di un po 'di ordine, è necessario aggiungere qualcosa come:

.order_by(Shoe.id.desc()) 

Se non si specifica l'ordine, è ancora possibile che si ottiene i dati dal database ordinato. Ma in questo caso, il database utilizza solo l'ordine che non richiede alcuna manipolazione di dati non necessaria. Sembra solo un dato ordinato, ma non lo è.

0

Ho anche lo stesso problema utilizzando un database MySQL. Questo è quello che ho fatto:

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

Ed è così che la mia domanda si presenta come:

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

FIELD() è una funzione nativa in MySQL.

EDIT: Quindi la query dovrebbe essere simile a questo:

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

Acclamazioni

3

Un modo ho risolto questo problema in passato, è quello di utilizzare un SQL CASE expression per raccontare il database in quale ordine I Mi piacerebbe che le file tornassero. Usando il tuo esempio:

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