2015-03-29 7 views
5

Ich habe ein Schuhmodell wie folgt aus:Sqlalchemy Filter nach Feld in der Liste, aber die ursprüngliche Reihenfolge beibehalten?

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

Ich habe eine Liste von IDs wie ids = [2,1,3] und wenn ich Abfrage auf dem Schuh-Modell, so dass die Ergebnisse haben ids in der ' IDs Liste, ich will zurück: [{id: 2, asin: "111"}, {ID: 1, asin: "113"}, {ID: 3, asin: "42"}] aber das Problem ist Wenn die folgende Abfrageanweisung nicht die ursprüngliche Reihenfolge beibehält, werden die Ergebnisse zufällig zurückgegeben. Wie behalte ich die Reihenfolge der Liste, nach der ich gefiltert habe?

falsch ein: Shoe.query.filter(Shoe.id.in_(my_list_of_ids)).all()

+0

Ich denke, das so ziemlich verwandt ist: http://stackoverflow.com/questions/7443243/sqlalchemy-order-by-field – alecxe

+0

Dieser nicht mit Kolben-sqlalchemy – user1835351

+0

funktioniert Warum sollte du willst sogar so etwas machen – adarsh

Antwort

5

Wenn Sie eine angemessene kleine Liste von IDs haben, könnten Sie einfach SQL-Abfragen auf jeden einzeln id ausführen:

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

Für eine große Anzahl von IDs, SQL-Abfragen werden eine lange Zeit in Anspruch nehmen. Dann sind Sie mit einer einzigen Abfrage besser und die Werte in der richtigen Reihenfolge in einem zweiten Schritt (entlehnt aus how to select an object from a list of objects by its attribute in python) setzen:

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] 

Dies wird vorausgesetzt, die IDs sind einzigartig (was sie in Ihrem Fall sein soll) . Die erste Methode löst eine Ausnahme aus, wenn mehrere Elemente mit derselben ID vorhanden sind.

-1

Was meinen Sie, wenn Sie „ursprüngliche Ordnung“ sagen? Datenbank hat nicht so etwas wie "ursprüngliche Reihenfolge". Wenn Sie etwas bestellen möchten, müssen Sie so etwas wie hinzufügen:

.order_by(Shoe.id.desc()) 

Wenn Sie nicht die Reihenfolge angeben, ist es noch möglich, dass Sie Daten aus der Datenbank bestellt erhalten. Aber in diesem Fall verwendet die Datenbank nur die Reihenfolge, die keine unnötige Datenmanipulation benötigt. Es sieht nur aus wie eine geordnete Daten, aber es ist nicht.

0

Ich habe auch das gleiche Problem mit einer MySQL-Datenbank. Das ist, was ich tat:

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

Und das ist, wie meine Frage wie folgt aussieht:

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

FIELD() ist eine native Funktion in MySQL.

EDIT: Also Ihre Abfrage sollte wie folgt aussehen:

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

Prost

3

Ein Weg, ich dieses Problem in der Vergangenheit gelöst haben, ist durch eine SQL CASE expression mit der Datenbank, in welcher Reihenfolge zu sagen, dass ich Ich würde die Zeilen zurückgeben. Mit Ihrem Beispiel:

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