我有一个像这样的鞋子模型:
class Shoe(db.Model):
id = db.Column(db.Integer, primary_key = True)
asin = db.Column(db.String(20), index = True)
我有一个id列表,如ids = [2,1,3],当我查询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()
答案 0 :(得分:11)
如果你有一个合理的小ID列表,你可以单独对每个id执行SQL查询:
[Shoe.query.filter_by(id=id).one() for id in my_list_of_ids]
对于大量ID,SQL查询将花费很长时间。然后,您最好使用单个查询并在第二步中将值放入正确的顺序(从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]
这假设id是唯一的(在你的情况下它们应该是这样)。如果存在多个具有相同id的元素,则第一种方法将引发异常。
答案 1 :(得分:7)
我过去解决这个问题的一种方法是使用SQL CASE expression告诉数据库我想要返回的行的顺序。使用您的示例:
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()
答案 2 :(得分:0)
使用MySQL数据库也存在同样的问题。这就是我所做的:
my_list = [13,14,5,6,7]
# convert my_list to str
my_list_str = ','.join(map(str, my_list))
这就是我的查询的样子:
checkpoints = (
db_session.query(Checkpoint)
.filter(Checkpoint.id.in_(my_list))
.order_by('FIELD(id, ' + my_list_str + ')')
.all()
)
FIELD()是MySQL中的本机函数。
编辑:所以你的查询应该是这样的:
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()
干杯
答案 3 :(得分:-2)
当你说"原始订单&#34 ;?时,你的意思是什么?数据库没有"原始订单"。如果您需要订单,则必须添加以下内容:
.order_by(Shoe.id.desc())
如果您没有指定订单,那么您仍然可以从数据库获取订购数据。但在这种情况下,数据库只使用不需要任何不必要的数据操作的顺序。它只是看起来像一个有序的数据,但它不是。