Grails多对多-查找包含特定对象列表的所有对象

Grails多对多-查找包含特定对象列表的所有对象,grails,gorm,Grails,Gorm,我有以下域模型: class Recipe { String title static hasMany = [ ingredients : Ingredient ] } class Ingredient { String ingredient static hasMany = [ recipes : Recipe ] static belongsTo = Recipe } Grails使用配料ID和配方ID创建了表RECIPE_配料 我如何通过传递一份

我有以下域模型:

class Recipe {
    String title
    static hasMany = [ ingredients : Ingredient ]
}

class Ingredient {
    String ingredient
    static hasMany = [ recipes : Recipe ]
    static belongsTo = Recipe
}
Grails使用配料ID和配方ID创建了表RECIPE_配料

我如何通过传递一份配料清单来获得一份食谱清单

def egg = new Ingredient(ingredient:"Egg")
def milk = new Ingredient(ingredient:"Milk")
def flour = new Ingredient(ingredient:"Flour")
def apple = new Ingredient(ingredient:"Apple")
def banana = new Ingredient(ingredient:"Banana")
def mango = new Ingredient(ingredient:"Mango")


def pizza = new Recipe(title:"Pizza")
pizza.addToIngredients(egg)
pizza.addToIngredients(milk)
pizza.addToIngredients(flour) 
pizza.save()

def salad = new Recipe(title:"Fruit Salad with milk")
salad.addToIngredients(apple)
salad.addToIngredients(banana)
salad.addToIngredients(mango)
salad.addToIngredients(milk)
salad.save()
例如:

[mango, milk] return me salad
[milk] return me salad and pizza
[milk, flour] return me pizza

在这里,您需要检查属于
配方的
成分集
是否包含您正在传递的
成分的子集。我想不出用
GORM
Criteira
来做这件事的直接方法。使用HQL可能会对此进行攻击:

public List<Recipe> fetchRecipe(List<String> ingredients){
    ingredients = ingredients.unique()
    Recipe.executeQuery('''
        SELECT recipe FROM Recipe AS recipe
        JOIN recipe.ingredients as ingredients
        WHERE ingredients.ingredient in :ingredients
        GROUP BY recipe
        HAVING COUNT(recipe) = :count
    ''', [ingredients: ingredients, count: ingredients.size().toLong()])
}
它将输出:

[Pizza, Fruit Salad with milk]
[Fruit Salad with milk]
[Pizza]
它的工作原理

  • 查询首先选择配料列表中含有任何配料的所有配方。只要配方中至少有一种成分,它就会被退回

  • 这会产生副作用,即列出每种匹配成分的配方。例如,如果一个配方包含两种成分,那么该配方将返回两次。GROUPBY子句使查询过滤掉那些重复的列表

  • 然而,这些重复的成分是这个黑客的关键:如果成分列表是一个唯一的列表,并且配方中不存在多次相同的成分,那么如果重复的数量等于成分的数量,那么配方就拥有所有必需的成分。这就是HAVING子句通过计算食谱的数量所做的


这里您需要检查属于
配方的
成分集是否包含您正在传递的
成分的子集。我想不出用
GORM
Criteira
来做这件事的直接方法。使用HQL可能会对此进行攻击:

public List<Recipe> fetchRecipe(List<String> ingredients){
    ingredients = ingredients.unique()
    Recipe.executeQuery('''
        SELECT recipe FROM Recipe AS recipe
        JOIN recipe.ingredients as ingredients
        WHERE ingredients.ingredient in :ingredients
        GROUP BY recipe
        HAVING COUNT(recipe) = :count
    ''', [ingredients: ingredients, count: ingredients.size().toLong()])
}
它将输出:

[Pizza, Fruit Salad with milk]
[Fruit Salad with milk]
[Pizza]
它的工作原理

  • 查询首先选择配料列表中含有任何配料的所有配方。只要配方中至少有一种成分,它就会被退回

  • 这会产生副作用,即列出每种匹配成分的配方。例如,如果一个配方包含两种成分,那么该配方将返回两次。GROUPBY子句使查询过滤掉那些重复的列表

  • 然而,这些重复的成分是这个黑客的关键:如果成分列表是一个唯一的列表,并且配方中不存在多次相同的成分,那么如果重复的数量等于成分的数量,那么配方就拥有所有必需的成分。这就是HAVING子句通过计算食谱的数量所做的


出于好奇,你有没有试过
配方。找到配料列表([牛奶,芒果])
应该是“鸡蛋加牛奶的比萨饼”;)出于好奇,您是否尝试过
配方。查找配料列表([牛奶,芒果])
这应该是“鸡蛋加牛奶的比萨饼”;)哦完美答案。非常感谢你。我来研究Grails,但不知道如何解决它。谢谢。哦。。完美答案。非常感谢你。我来研究Grails,但不知道如何解决它。非常感谢。