gpt4 book ai didi

Cakephp3.1 : Using matching() and notMatching() on the same associated model at once

转载 作者:行者123 更新时间:2023-12-02 16:19:22 26 4
gpt4 key购买 nike

我想实现食谱及其相关成分的搜索功能。用户应该指定他想要从搜索中排除的成分,同时指定他正在寻找的食谱中包含的成分。

这是我的两个发现者:

public function findByContainingIngredients(Query $query, array $params)
{
$ingredients = preg_replace('/\s+/', '', $params['containing_ingredients']);

if($ingredients) {
$ingredients = explode(',', $ingredients);
$query->distinct(['Recipes.id']);
$query->matching('Ingredients', function ($query) use($ingredients) {
return $query->where(function ($exp, $query) use($ingredients) {
return $exp->in('Ingredients.title', $ingredients);
});
});
}
return $query;
}


public function findByExcludingIngredients(Query $query, array $params)
{
$ingredients = preg_replace('/\s+/', '', $params['excluding_ingredients']);

if($ingredients) {
$ingredients = explode(',', $ingredients);
$query->distinct(['Recipes.id']);
$query->notMatching('Ingredients', function ($query) use ($ingredients) {
return $query->where(function ($exp, $query) use ($ingredients) {
return $exp->in('Ingredients.title', $ingredients);
});
});

}
return $query;
}

在 Controller 中我调用:

            $recipes = $this->Recipes->find()
->find('byExcludingIngredients', $this->request->data)
->find('byContainingIngredients', $this->request->data);

如果用户从搜索中排除某种成分并指定他想要包含的一种或多种成分,则结果为零。当我查看生成的 SQL 时,我发现了问题:

SELECT 
Recipes.id AS `Recipes__id`,
Recipes.title AS `Recipes__title`,
.....

FROM
recipes Recipes
INNER JOIN ingredients Ingredients ON (
Ingredients.title IN (: c0)
AND Ingredients.title IN (: c1)
AND Recipes.id = (Ingredients.recipe_id)
)
WHERE
(
Recipes.title like '%%'
AND (Ingredients.id) IS NULL
)
GROUP BY
Recipes.id,
Recipes.id

问题是“AND (Ingredients.id) IS NULL”。这条线使得包含成分的结果消失。我的方法:

  • 在关联上调用 notMatching() 两次时创建别名。我认为这在Cake3.1中是不可能的
  • 在 PK/FK 和排除的标题上使用左连接并创建别名。基本上是编写我自己的 notMatching 函数。这可行,但感觉不对。

还有其他解决方案吗?

最佳答案

对于任何来到此页面并得出结论不能在同一关联类上组合 matching()notMatching() 的人:

是的,(无论如何从 Cake 3.4.9 开始)可以进行这样的查找。但是您必须为目标表使用不同的别名 - 这是与通常的类名不同的别名。

因此,在 OP 的情况下,您可以将其放入 RecipesTable.php 中:

public function initialize(array $config) {
... usual stuff

$this->belongsToMany('Ingredients', [
'foreignKey' => 'recipe_id',
'targetForeignKey' => 'ingredient_id',
'joinTable' => 'ingredients_recipes'
]);
// the next association uses an alias,
// but is otherwise *exactly* the same as the previous assoc.
$this->belongsToMany('ExcludedIngredients', [
'className' => 'Ingredients',
'foreignKey' => 'recipe_id',
'targetForeignKey' => 'ingredient_id',
'joinTable' => 'ingredients_recipes'
]);
}

您应该能够编写如下所示的查找语句:

$this->find()
-> ... usual stuff
->matching('Ingredients',function($q) use($okIngredients) {
... check for ingredients ...
})
->notMatching('ExcludedIngredients', function($q) use($excludedIngredients) {
... check for ingredients ...
});

确实有效。不幸的是,当我在类似的情况下使用它时,'Recipes' 表中有数千 行,查询需要 40 秒才能运行。所以我必须回去并用手工制作的连接替换 notMatching()

关于Cakephp3.1 : Using matching() and notMatching() on the same associated model at once,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40978501/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com