• Doctrine2. Как выбрать и гидрировать связанные коллекции?

    @liongen Автор вопроса
    novrm, посмотрите внимательно на вопрос. Перефразирую, нужна коллекция А с коллекцией В у которой нужна коллекция С. У каждой из коллекций стоит своя сортировка и свой лимит. Сможете решить такое одним запросом?

    Ну а что касается миллионов запросов к БД, то это надо решать уже на другом уровне (например кэшированием)
  • Doctrine2. Как выбрать и гидрировать связанные коллекции?

    @liongen Автор вопроса
    BoShurik


    {% for category in categories %}
        {% for post in category.lastPosts %}
             {% for comment in post.lastComments %}
                  {{ comment.content }}
             {% endfor %}
        {% endfor %}
    {% endfor %}



    этот пример работает как надо! видимо я и сам не до конца понял всю проблематику вопроса..( конечно создается огромное количество запросов к БД, но по другому и не выбрать такую коллекцию данных (пользовательские переменные не в счет, в постгресе например их вовсе нет). Теперь я вот думаю, а это нормально иметь такие методы в entity:

    public function getLatestPosts()
        {
            $collection = $this->getPosts();
            $criteria = Criteria::create()
                ->orderBy(["id" => Criteria::DESC])
                ->setFirstResult(0)
                ->setMaxResults(20);
    
            return $collection->matching($criteria);
        }


    Что, если у меня добавятся параметры, например направление сортировки или максимальное кол-во измениться?
  • Doctrine2. Как выбрать и гидрировать связанные коллекции?

    @liongen Автор вопроса
    BoShurik, а ведь верно) до меня только дошло) спасибо!)
  • Doctrine2. Как выбрать и гидрировать связанные коллекции?

    @liongen Автор вопроса
    novrm, это решило бы мою проблему (разве что таблички для джойна не стали бы за миллион записей), но я так и не понял, как у вас получается гидрировать кучу однородных объектов без потерь. Посмотрите ту статью, что скинул BoShurik там подробно описана эта ситуация. Еще советую склонировать репу https://github.com/Ocramius/Doctrine2StepHydration и поиграться с single-fetch-join.php и multi-step-hydration.php
  • Doctrine2. Как выбрать и гидрировать связанные коллекции?

    @liongen Автор вопроса
    тот запрос, что вы привели имеет такой же недостаток :) Если вы хотите сделать одним запросом, то тут нужны пользовательские переменные. И сомневаюсь, что доктрина так умеет


    BoShurik, так и не понял почему этот запрос не отработает) только что проверил - все ок, кстати сама доктрина такие запросы строит если в fetch (или setFetchMode()) прописать EAGER (но работает вроде только для связей ManyToOne или ManyToMany)
  • Doctrine2. Как выбрать и гидрировать связанные коллекции?

    @liongen Автор вопроса
    novrm, так это же обычный lazy loading, на каждый {{ categoryHasProduct.getProduct().getShortName() }} будет улетать запрос в БД, а если у меня таких сотня на страницу?
  • Doctrine2. Как выбрать и гидрировать связанные коллекции?

    @liongen Автор вопроса
    Кроме того я не уверен, что вы понимаете суть гидратации.


    Если смотреть в контексте доктрины, гидрация (hydration) - процесс преобразования результирующего набора данных (для примера, полученных из БД) в определенную структуру (например обьект или массив).

    Если вы желаете ИЗВЛЕКАТЬ данные из БД и выводить их "in View" в виде неких списков - то гидратация вам не нужна.


    я вам говорю не о выводе простых списков, а о выводе иерархии
  • Doctrine2. Как выбрать и гидрировать связанные коллекции?

    @liongen Автор вопроса
    BoShurik, верно. Этот SQL с ошибкой, я его указал для примера. Так например делает ORM в Laravel в режиме жадной загрузки: сначала выбираются категории из БД, из них собираются идентификаторы для постов и уже они одним запросом забираются из БД, после этого посты мапятся коллекциями к категориям.

    На DQL этот запрос бы выглядел как то так:

    $query = $em->createQuery('SELECT p FROM AppBundle\Entity\Post p WHERE p.category_id IN (?1) ORDER BY p.id DESC');
            $query->setMaxResults(20);
            $query->setParameter(1, $categoriesIds);
            $posts = $query->getResult();


    Я специально не стал описывать получение $categoriesIds
  • Doctrine2. Как выбрать и гидрировать связанные коллекции?

    @liongen Автор вопроса
    novrm, Вы используете свои стратегии для гидрирования? Странно, Ocramius указал в том посте, что помогает только мульти шаговая гидрация с жадной выборкой сначала одной коллекции, а потом другой (в посте есть примеры). Клонировал его репу и реально скорость гидрации с двумя джойнами в одном запросе падает в разы. В любом случае, его кейс не подходит. Я задал ему вопрос лично, с примером такого кейса из этого вопроса, он ответил что только тремя запросами надо делать. Я в принципе и сам понимаю что нужно делать разные запросы, но как потом это все объединить в одну коллекцию с вложенными коллекциями на доктрине ума не приложу.

    P.S. кстати смотрю люди не всегда заморачиваются такой оптимизацией (достаточно популярный проект во Франции) https://github.com/EnMarche/en-marche.fr/blob/deve...
  • Doctrine2. Как выбрать и гидрировать связанные коллекции?

    @liongen Автор вопроса
    BoShurik, смотрите, если у меня есть коллекция категорий состоящая из 5 штук, при итерации этой коллекции и обращению к category.lastPosts в твиге, будет идти запрос в БД за списком постов, итого 1 запрос на выборку категорий + 5 запросов на выборку постов для каждой = 6 запросов. А если пойти еще глубже?

    вы можете получить посты только из одной категории. Так и задумано?


    Почему из одной? Как минимум из 5, может я что то пропустил?
  • Doctrine2. Как выбрать и гидрировать связанные коллекции?

    @liongen Автор вопроса
    К сожалению не подходит. Это может работать, если у нас один объект содержит коллекцию других сущностей, но если у меня допустим 5 категорий и мне нужно для каждой по особому выбрать посты (а у них еще и комменты в определенном порядке), то это нужно протерировать каждую сущность и выполнить у каждой запрос к БД