Sqlalchemy filter by field in list but keep original order?

后端 未结 4 1367
时光说笑
时光说笑 2021-02-12 22:35

I have a Shoe model like this:

class Shoe(db.Model):
id = db.Column(db.Integer, primary_key = True)
asin = db.Column(db.String(20), index = True)
相关标签:
4条回答
  • 2021-02-12 22:36

    If you have a reasonable small list of ids, you could just perform SQL queries on each id individually:

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

    For a large number of ids, SQL queries will take a long time. Then you are better off with a single query and putting the values in the correct order in a second step (borrowed from 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]
    

    This is assuming the id's are unique (which they should be in your case). The first method will raise an exception if there are multiple elements with the same id.

    0 讨论(0)
  • 2021-02-12 22:36

    I also have the same problem using a MySQL database. This is what I did:

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

    And this is how my query looks like:

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

    FIELD() is a native function in MySQL.

    EDIT: So your query should look like this:

    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

    0 讨论(0)
  • 2021-02-12 22:48

    What do you mean when you say "original order"? Database doesn't have such thing as "original order". If you need some order, you must add something like:

    .order_by(Shoe.id.desc())
    

    If you don't specify the order, it's still possible that you get ordered data from database. But in this case, database just uses order that doesn't needs any unnecessary data manipulation. It's just looks like an ordered data, but it isn't.

    0 讨论(0)
  • 2021-02-12 22:57

    One way I've solved this problem in the past is by using a SQL CASE expression to tell the database in what order I'd like the rows returned. Using your example:

    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()
    
    0 讨论(0)
提交回复
热议问题