2014-10-09 142 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