Sqlalchemy按列表中的字段过滤但保留原始订单?

use*_*351 12 python sqlalchemy flask-sqlalchemy

我有一个像这样的鞋子模型:

class Shoe(db.Model):
id = db.Column(db.Integer, primary_key = True)
asin = db.Column(db.String(20), index = True)
Run Code Online (Sandbox Code Playgroud)

我有一个像ids = [2,1,3]的id列表,当我在Shoe模型上查询结果在'ids'列表中有id时,我想回来:[{id:2,asin:" 111"},{id:1,asin:"113"},{id:3,asin:"42"}]但问题是使用以下查询语句不保留原始顺序,结果将会到来随机回来.如何保持我过滤的列表顺序?

不正确的一个: Shoe.query.filter(Shoe.id.in_(my_list_of_ids)).all()

Rob*_*Rob 12

如果你有一个合理的小ID列表,你可以单独对每个id执行SQL查询:

[Shoe.query.filter_by(id=id).one() for id in my_list_of_ids]
Run Code Online (Sandbox Code Playgroud)

对于大量ID,SQL查询将花费很长时间.然后,您最好使用单个查询并在第二步中以正确的顺序放置值(借用于如何通过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]
Run Code Online (Sandbox Code Playgroud)

这假设id是唯一的(它们应该在你的情况下).如果有多个具有相同id的元素,则第一种方法将引发异常.


bjm*_*jmc 9

我过去解决这个问题的一种方法是使用SQL CASE表达式告诉数据库我想要返回的行的顺序.使用你的例子:

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()
Run Code Online (Sandbox Code Playgroud)

  • 仅当您想按 id 字段排序时才有效,而当您需要在“my_list_of_ids”中保留预先存在的排序时则无效。 (2认同)