2015-05-26 17 views
13

Sto creando un pacchetto di messaggi in cui i messaggi sono raggruppati per contatti. Nella mia pagina di indice, visualizzo thread diversi. Quando fai clic su un thread, mostra tutti i messaggi scambiati tra te e il tuo contatto. Io uso un generatore di query per visualizzare i filetti sulla mia pagina di indice:Query Builder e Group By su due colonne in Symfony2/Doctrine genera duplicati

$qb = $this->createQueryBuilder('m') 
    ->where('m.from = ?1 or m.to = ?1') 
    ->groupBy('m.to, m.from') 
    ->orderBy('m.date', 'DESC') 
    ->setParameter(1, $user->getId()) 
    ->setMaxResults($pagination) // limit 
    ->setFirstResult($pagination * $page) // offset 
; 

Se ho 3 voci, per exemple:

+----+------+----+ 
| id | from | to | 
+----+------+----+ 
| 1 | 1 | 2 | 
+----+------+----+ 
| 2 | 2 | 1 | 
+----+------+----+ 
| 3 | 1 | 2 | 
+----+------+----+ 

mi aspetto:

+----+------+----+ 
| id | from | to | 
+----+------+----+ 
| 3 | 1 | 2 | 
+----+------+----+ 

ma ottengo :

+----+------+----+ 
| id | from | to | 
+----+------+----+ 
| 2 | 2 | 1 | 
+----+------+----+ 
| 3 | 1 | 2 | 
+----+------+----+ 

Ho trovato un modo per farlo con SQL, utilizzando lo stesso alias per from_id e to_id:

SELECT id, from_id as c, to_id as c FROM Message WHERE c = 1 GROUP BY from_id, to_id 

Ma non so come farlo con Doctrine.

EDIT:

Fino a quando ho un'idea migliore, io uso una chiave per facilmente "gruppo da".

// entity 

/** 
* @ORM\Column(name="key", type="string", length=40) 
*/ 
private $key; 

/** 
* @ORM\PrePersist() 
*/ 
public function setOnPrePersist() 
{ 
    if($this->from < $this->to) { 
     $key = $this->from . 't' . $this->to; 
    } else { 
     $key = $this->to . 't' . $this->from; 
    } 

    $this->key = $key; 
} 

// query builder 

$qb = $this->createQueryBuilder('m') 
    ->where('m.from = ?1 or m.to = ?1') 
    ->groupBy('m.key') 
    ->orderBy('m.date', 'DESC') 
    ->setParameter(1, $user->getId()) 
    ->setMaxResults($pagination) // limit 
    ->setFirstResult($pagination * $page) // offset 
; 

return $qb->getQuery()->getResult(); 
+0

try selectiong solo l'ID aggiungendo '$ qb-> selezionare ("m.to, m.from");' – Matteo

+0

ho cercato $ q = $ em-> createQueryBuilder() -> seleziona ('m.to, m.from') -> da ('MyAppDiscussionBundle: Message', 'm') ... ma ottengo un errore: [Semantical Error] riga 0, colonna 9 vicino 'a, m.from FROM ': Errore: PathExpression non valido. Deve essere un'espressione StateFieldPathExpression. – Eddy

+0

Ti stai aspettando la cosa sbagliata. In SQL, usando 'GROUP BY from_id, to_id' significa che da 1 a 2 e da 2 a 1 sono 2 gruppi diversi. – Jean

risposta

0

provare il successivo alla dottrina utilizzando il metodo DQL -

$query = $em->createQuery("SELECT m.id, m.from_id as c, m.to_id as c FROM AcmeDemoBunlde:Message as m WHERE m.c = 1 GROUP BY m.from_id, m.to_id"); 

$messageDetails = $query->getResult(); 

Invece di AcmeDemoBundle sostituire con la appropriata nome del bundle.

+0

Non funziona, ma sto esplorando una soluzione utilizzando DQL e IDENTITY() http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language .html – Eddy

1

nel caso in cui vi siano molte colonne in 'group by' è necessario utilizzare il metodo addGroupBy().

$qb = $this->createQueryBuilder('m') 
    ->where('m.from = ?1 or m.to = ?1') 
    ->groupBy('m.to') 
    ->addGroupBy('m.from') 
    ->orderBy('m.date', 'DESC') 
    ->setParameter(1, $user->getId()) 
    ->setMaxResults($pagination) // limit 
    ->setFirstResult($pagination * $page) // offset 
; 

:)