How to get a SQL Alchemy object of distinct items with filter on related objects

别等时光非礼了梦想. 提交于 2019-12-25 07:46:45

问题


I am trying to get a SQL Alchemy query of distinct items below filtering on related objects, the equivalent of the below query:

SELECT distinct items.item_id, items.item_name
FROM items
INNER JOIN categories as cat on items.category_id = cat.category_id
INNER JOIN stores on cat.store_id = stores.store_id
WHERE store.store_id = 123    

I have created the models as below with foreign keys included but when I run the query below it does not filter correctly.

items_query = (db.session.query(Store, Item)
               .filter(Store.store_id == 123)
               ).all()



#SQL Alchemy Models 
class Store(db.Model):
    __tablename__ = 'stores'
    store_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    store_name = db.Column(db.String(100), unique=True, nullable=False)

    def __repr__(self):
        return '<Store>'+str(self.store_name)

class Category(db.Model):
    __tablename__ = 'categories'
    category_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    category_name = db.Column(db.String(100), unique=True, nullable=False)
    store_id = db.Column(db.Integer, db.ForeignKey('stores.store_id'))
    store = db.relationship('Store', backref=db.backref('categories', lazy='dynamic'))

    def __repr__(self):
        return '<Category>'+str(self.category_name)

class Item(db.Model):
    __tablename__ = 'items'
    item_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    item_name = db.Column(db.String(150), unique=True, nullable=False)
    category_id = db.Column(db.Integer, db.ForeignKey('categories.category_id'))
    category = db.relationship('Category', backref=db.backref('items', lazy='dynamic'))

    def __repr__(self):
        return '<Item>'+str(self.item_name)

Could anyone assist me to form the query better?


回答1:


With

(db.session.query(Store, Item)
 .filter(Store.store_id == 123)
 ).all()

you'll get an implicit cross join between Store and Item, which is clearly not what you want.

First build the required joins either explicitly using the relationships:

query = db.session.query(Item.item_id, Item.item_name).\
    join(Item.category).\
    join(Category.store)

or the shorthand form:

query = db.session.query(Item.item_id, Item.item_name).\
    join("category", "store")

Then apply your WHERE clause:

query = query.filter(Store.store_id == 123)

And then distinct():

query = query.distinct()

To sum it up:

query = db.session.query(Item.item_id, Item.item_name).\
    join("category", "store").\
    filter(Store.store_id == 123).\
    distinct().\
    all()

Also since you've unique constraint on Item.item_name and the joins should not produce multiple rows per Item because of the direction of the one to many relationships, the distinct() should be unnecessary.



来源:https://stackoverflow.com/questions/43110595/how-to-get-a-sql-alchemy-object-of-distinct-items-with-filter-on-related-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!