Получение нечетного поведения из $query-> setMaxResults()

Когда я вызываю setMaxResults в запросе, кажется, что нужно рассматривать максимальное число как "2", независимо от его фактического значения.

function findMostRecentByOwnerUser(\Entities\User $user, $limit)
{
    echo "2: $limit<br>";
    $query = $this->getEntityManager()->createQuery('
        SELECT t
        FROM Entities\Thread t
        JOIN t.messages m
        JOIN t.group g
        WHERE 
            g.ownerUser = :owner_user
        ORDER BY m.timestamp DESC
    ');
    $query->setParameter("owner_user", $user);
    $query->setMaxResults(4);
    echo $query->getSQL()."<br>";
    $results = $query->getResult();
    echo "3: ".count($results);
    return $results;
}

Когда я прокомментирую строку setMaxResults, я получаю 6 результатов. Когда я оставлю это, я получаю 2 последних результата. Когда я запускаю сгенерированный код SQL в phpMyAdmin, я получаю 4 последних результата. Сгенерированный SQL для ссылки:

SELECT <lots of columns, all from t0_>
FROM Thread t0_ 
INNER JOIN Message m1_ ON t0_.id = m1_.thread_id 
INNER JOIN Groups g2_ ON t0_.group_id = g2_.id 
WHERE g2_.ownerUser_id = ? 
ORDER BY m1_.timestamp DESC 
LIMIT 4

Edit

При чтении документации DQL "Ограничение" я натолкнулся на следующее:

Если в вашем запросе содержится сборка, связанная с fetch, в которой указаны методы ограничения результата, они не работают так, как вы ожидали. Set Max Results ограничивает количество строк результатов базы данных, однако в случае собраний, связанных с выборкой, один корневой объект может появляться во многих строках, эффективно увлажняя меньше заданного количества результатов.

Я уверен, что я не собираюсь вносить коллекцию, связанную с fetch. У меня создалось впечатление, что сборка, связанная с извлечением, - это то, где я делаю что-то вроде SELECT t, m FROM Threads JOIN t.messages. Я неверен в своем понимании этого?

Ответ 2

Использование ->groupBy('your_entity.id') похоже на решение проблемы!

Ответ 3

Я решил ту же проблему, только извлекая содержимое главной таблицы и имея все объединенные таблицы, полученные как fetch="EAGER", которые определены в Entity (описано здесь http://www.doctrine-project.org/docs/orm/2.1/en/reference/annotations-reference.html?highlight=eager#manytoone).

class VehicleRepository extends EntityRepository
{
    /**
     * @var integer
     */
    protected $pageSize = 10;

    public function page($number = 1)
    {
        return $this->_em->createQuery('SELECT v FROM Entities\VehicleManagement\Vehicles v')
            ->setMaxResults(100)
            ->setFirstResult($number - 1)
            ->getResult();
    }
}

В моем примере репо вы можете видеть, что я только взял таблицу автомобилей, чтобы получить правильную сумму результата. Но все свойства (например, make, model, category) сразу получаются.

(Я также повторил содержимое Entity, потому что мне нужен Entity, представленный как массив, но это не должно иметь значения afaik.)

Здесь выдержка из моей сущности:

class Vehicles
{
    ...

    /**
     * @ManyToOne(targetEntity="Makes", fetch="EAGER")
     * @var Makes
     */
    public $make;

    ...
}

Его важный, который вы правильно сопоставляете каждому объекту, иначе он не будет работать.