symfony4.1条令很多减少了查询次数

bybem2ql  于 2021-06-19  发布在  Mysql
关注(0)|答案(2)|浏览(404)

我在做一个项目。实体是blog、category、tags。博客和标签有很多关系。我的存储库查询通过标签过滤器获取数据是。
代码1:

/**
 * @return BlogPost[]
 */
public function getAllActivePostsByTags($value, $order = "DESC", $currentPage = 1, $limit = 10)
{
    $query = $this->createQueryBuilder('p')
        // ->select('p','t')
        ->innerJoin('p.blogTags', 't')
        ->where('t.slug = :val')
        ->setParameter('val', $value)
        ->orderBy('p.id', $order)
        ->getQuery();

    $paginator = $this->paginate($query, $currentPage, $limit);

    return $paginator;
}

这个代码很好用。所有标签(帖子中没有标签)都正确显示。但是db query的编号是14。当我取消注解select时,
代码2:

/**
 * @return BlogPost[]
 */
public function getAllActivePostsByTags($value, $order = "DESC", $currentPage = 1, $limit = 10)
{
    $query = $this->createQueryBuilder('p')
        ->select('p','t')
        ->innerJoin('p.blogTags', 't')
        ->where('t.slug = :val')
        ->setParameter('val', $value)
        ->orderBy('p.id', $order)
        ->getQuery();

    $paginator = $this->paginate($query, $currentPage, $limit);

    return $paginator;
}

查询编号为9。但是每个帖子的标签只有一个(不显示单个帖子的所有标签)。
明确信息:
它显示整个blogpost列表。
但不是所有的标签。
每个帖子只显示一个标签。
问题:code1是正确的(no of db query=14)还是我必须稍微调整一下以减少db命中率。请在这方面指导我。

6xfqseft

6xfqseft1#

感谢@jannes botis的更新。但在我看来,代码本身是错误的。需要稍微改变一下。
博客标签.php

/**
 * @ORM\ManyToMany(targetEntity="BlogPost", mappedBy="blogTags")
 */
private $blogPosts;

博客帖子.php

/**
 * @var Collection|BlogTags[]
 *
 * @ORM\ManyToMany(targetEntity="BlogTags", inversedBy="blogPosts", cascade={"refresh"})
 * @ORM\JoinTable(
 *  name="fz__blog_n_tag",
 *  joinColumns={
 *      @ORM\JoinColumn(name="blog_id", referencedColumnName="id")
 *  },
 *  inverseJoinColumns={
 *      @ORM\JoinColumn(name="tag_id", referencedColumnName="id")
 *  }
 * )
 * @ORM\OrderBy({"name": "ASC"})
 */
private $blogTags;

这创建了join\u表。好的,我有一张table。尽管这段代码是供某人参考的。
控制器.php

// This is my old Code
$bp = $em->getRepository('App:BlogPost')->getAllActivePostsByTags($slug, "DESC", $page, self::PAGE_LIMIT);
// This is my New Code
$bp = $em->getRepository('App:BlogTags')->getAllActivePostsByTags($slug, "DESC", $page, self::PAGE_LIMIT);

存储库.php

public function getAllActivePostsByTags($value, $order = "DESC", $currentPage = 1, $limit = 10)
    {
        $query = $this->createQueryBuilder('t')
            ->select('t','p','tx')
            ->innerJoin('t.blogPosts', 'p')
            ->innerJoin('p.blogTags', 'tx')
            ->where('p.isActive = :val1')
            ->andWhere('t.slug = :val2')
            ->setParameter('val1', true)
            ->setParameter('val2', $value)
            ->orderBy('p.id', $order)
            ->getQuery();

        $paginator = $this->paginate($query, $currentPage, $limit);

        return $paginator;
    }

我没有完全改变我的旧树枝文件。因为它在很多地方都会出错。因为现在我用标签来代替博客。所以我用

{% include 'frontend/page/blog_home.html.twig' with { 'bp':bp|first.blogPosts } %}

在这个(细枝文件)上帮助我:只有一个标签,这就是为什么第一个细枝过滤器用这个细枝过滤器来澄清我。我做得对。给我一些改进的建议。我尝试了bp[0]这个trows错误。
最后:通过在控制器中使用旧代码,它返回14分贝的命中率。现在它只返回8。即使在一篇文章中有更多的标签(但旧的会返回更多)。

ffscu2ro

ffscu2ro2#

这是两种情况下的预期行为。
案例1)您只需选择blogpost实体。所以你告诉条令去获取所有blogpost,这些blogpag有slug=value。生成的sql查询只返回blog\u post表中的列值,因此只对返回的blogpost实体进行水合物化处理,而不会对每个blogpost中的blogtag集合进行水合物化处理。
当您尝试访问blogpost的标签时,会生成一个新的查询来获取并添加其集合。
这就是在这种情况下得到更多查询的原因。
案例2)您还可以选择过滤后的blogtag实体,并且只将这个过滤后的blogtag添加到每个blogpost的集合中。
当您尝试访问blogpost的blogtag时,您会得到满足querybuilder中条件的过滤后的blogtag。
要强制条令从数据库“重新加载”数据,应刷新blogpost实体:

$em->refresh($blogPost);

并在关系定义的级联操作上包括refrech选项:

@OneToMany(targetEntity="BlogTag", mappedBy="post", cascade={"refresh"})

参考文献:
级联刷新在条令2中意味着什么
刷新对象:不同的问题但解决方案相同

相关问题