2014-10-09 80 views
0

我正在构建配方数据库。我试图建立一个查询我得到所有包含某种成分(如洋葱,胡萝卜)的接收者,但我不是如何构建我的查询。本质上,我试图得到一个列表(给定适量的连接)有一个Ingredient.name ='洋葱'。我的模型如下:通过关联表格选择项目

ingredients = db.Table('ingredients', 
    db.Column('modified_ingredient', db.Integer, db.ForeignKey('modified_ingredient.id')), 
    db.Column('ingredient', db.Integer, db.ForeignKey('ingredient.id')) 
    ) 

modifiers = db.Table('modifiers', 
    db.Column('modified_ingredient', db.Integer, db.ForeignKey('modified_ingredient.id')), 
    db.Column('modifier', db.Integer, db.ForeignKey('modifier.id')) 
    ) 

modified_ingredients = db.Table('modified_ingredients', 
    db.Column('recipe', db.Integer, db.ForeignKey('recipe.id')), 
    db.Column('modified_ingredient', db.Integer, db.ForeignKey('modified_ingredient.id')) 
    ) 

class Recipe(db.Model): 
    __tablename__ = 'recipe' 

    id = db.Column(db.Integer, primary_key=True) 

    name = db.Column(db.String(256)) 
    description = db.Column(db.Text) 
    directions = db.Column(db.Text) 
    prep_time = db.Column(db.Integer) 
    cook_time = db.Column(db.Integer) 
    image = db.Column(db.LargeBinary()) 
    ingredients = db.relationship('ModifiedIngredient', secondary=modified_ingredients) 

class Ingredient(db.Model): 
    __tablename__ = 'ingredient' 

    id = db.Column(db.Integer, primary_key=True) 

    name = db.Column(db.String(30), index=True, unique=True) 

class Modifier(db.Model): 
    __tablename__ = 'modifier' 

    id = db.Column(db.Integer, primary_key=True) 

    name = db.Column(db.String(30), index=True, unique=True) 

class ModifiedIngredient(db.Model): 
    __tablename__ = 'modified_ingredient' 

    id = db.Column(db.Integer, primary_key=True) 

    amount = db.Column(db.Integer) 
    unit = db.Column(db.String(20)) 
    ingredients = db.relationship('Ingredient', secondary=ingredients, 
     backref=db.backref('ingredients', lazy='dynamic'), lazy='dynamic') 
    modifiers = db.relationship('Modifier', secondary=modifiers, 
     backref=db.backref('modifiers', lazy='dynamic'), lazy='dynamic') 

这大部分是我对SQL和SQLAlchemy的经验不足,它困扰着我。我知道我加入了一些东西,但我不确定如何用一种有效的方式来表达它。

+0

有点偏离主题 - 但感觉你的模特有点偏离。目前,“一个食谱有许多修改成分,每个修改成分都由许多成分和许多修饰词组成”。所以我认为'ModifiedIngredient'应该与'Ingredient'和'Modifier'成为一对多的关系,而不是像现在这样的多对多关系?这将使关系“一个配方有许多ModifiedIngredients,每个ModifiedIngredient由一个修改器和一个成分组成”。 – Doobeh 2014-10-09 21:19:09

+0

好吧,一种成分可以有多种改变(例如炖西红柿和切丁) – Atrus 2014-10-09 22:15:26

+0

听起来像你想要设置所有可能的项目,所以你可以说'给我看所有西红柿',它会显示你罐头,切丁,粉碎,整体等,但不脱咖啡因。但是'Recipe'和'ModifiedIngredient'之间的关系意味着你不能真的那样做。 '番茄汤'食谱:它会想'ModifiedIngredient(amount = 2,unit ='Can',ingredients = [Ingredient(name ='Canned Tomato')],modifiers = [Modifier('Crushed')])'which是不可转让的'肉酱'配方,只需要1个丁可以 - 它需要一个新的'ModifiedIngredient'条目,多个修饰符就不会工作 – Doobeh 2014-10-10 13:04:17

回答

2

选项1:很整洁,但可能不是最有效的因嵌套EXISTS条款:

q = (db.session.query(Recipe) 
    .filter(Recipe.ingredients.any(
     ModifiedIngredient.ingredients.any(
      Ingredient.name == 'onion') 
    ))) 

选项2:应该更快,但如果你只查询某些列(使用query(Recipe.name, ..)代替如下整个对象),你会用,每次使用Recipe行的多个结果,因为JOINs结束:

q = (db.session.query(Recipe) 
    .join(Recipe.ingredients) 
    .join(Ingredient, ModifiedIngredient.ingredients) 
    .filter(Ingredient.name == 'onion') 
    ) 
+0

我实际上与选项二一起,我已经找到了一个在你发布这个之前很少。如何使用这个来获得多种成分,因为.filter(Ingredient.name =='onion',Ingredient.name =='tomato')似乎没有工作 – Atrus 2014-10-09 22:19:36

+0

如果你需要'和'条件,你可以添加另一个过滤器:'.filter(Ingredient.name =='tomato')'。如果你需要'或',那么'.filter(or_(Ingredient.name =='onion',Ingredient.name =='tomato'))'会做到这一点。 – van 2014-10-09 22:57:15