Доктрина Symfony4.1 ManyToMany Уменьшает количество запросов - PullRequest
0 голосов
/ 20 ноября 2018

Я работаю над проектом.Сущность - это Блог, Категория, Теги.Блог и теги находятся в ManyToMany отношениях.Мой запрос к хранилищу для выборки данных по фильтру тегов:

CODE1:

/**
 * @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 .Затем, когда я раскомментирую , выберите следующим образом:

CODE2:

/**
 * @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 правильным (Нет запроса к БД = 14) илиНужно ли немного подправить, чтобы уменьшить количество попаданий в БД.Пожалуйста, объясните мне это.

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Спасибо @Jannes Botis за обновление.Но в моем случае сам код неверен.Здесь нужно небольшое изменение.

BlogTags.php

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

BlogPost.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_table. Уже у меня есть join_table.Хотя этот код для справки.

Controller.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);

Repository.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]. Это выдает ошибку.

Наконец: При использовании старого кода в контроллере возвращается 14 дБ.Теперь он возвращает только 8. Даже в сообщении больше тегов (но старый возвращает больше).

0 голосов
/ 16 декабря 2018

Это ожидаемое поведение в обоих случаях.

Случай 1) Вы просто выбираете сущности BlogPost.Таким образом, вы говорите доктрине, что нужно выбрать все BlogPosts, у которых есть BlogTag со значением slug = value.Созданный SQL-запрос возвращает только значения столбцов из таблицы blog_post, и поэтому гидратирует только возвращенные сущности BlogPost , он не гидратирует коллекцию BlogTags внутри каждого BlogPost.

Когда вы пытаетесь получить доступтеги BlogPost создается новый запрос для получения и гидратации его коллекции.

По этой причине вы получаете больше запросов в этом случае.

Случай 2) Вы также выбираете отфильтрованные объекты BlogTag и доктрина гидратирует (помещает) только этот отфильтрованный BlogTag в каждую коллекцию BlogPost.

Когдавы пытаетесь получить доступ к BlogTag для BlogPost, вы получаете отфильтрованный, соответствующий условию в построителе запросов.

Чтобы заставить доктрину «перезагрузить» данные из базы данных, вы должны refresh сущность blogPost:

 $em->refresh($blogPost);

, а также опция refrech для каскадных операций определения отношения:

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

См.ences:

...