2012-04-16 14 views
7

Doctrine ile Symfony 2 kullanıyorum ve çok sayıda derneğe katılan iki varlığım var. Diyelim ki iki varlığım var: Kullanıcı ve Grup ve db'deki ilgili tablolar kullanıcı, grup ve kullanıcı_ grubu.DQL çok fazla ve sayısız

DQL'de en çok bulunan en popüler 10 grup almak istiyorum, ancak birleşim tablosunda (users_groups) sorgu yürütme sözdizimini bilmiyorum. Doktrin kılavuzuna çoktan baktım ama çözümü bulamadım, sanırım hala DQL hakkında öğrenecek çok şeyim var. Düz sql olarak

olacağını:

select distinct group_id, count(*) as cnt from users_groups group by group_id order by cnt desc limit 10 

Beni bu DQL çevirmek yardım eder misiniz?

Güncelleme (sınıflar):

$dql = "SELECT g.id, count(u.id) as cnt FROM Entity\Group g " . 
    "JOIN g.users u GROUP BY g.id ORDER BY cnt DESC LIMIT 10;"; 
$query = $em->createQuery($dql); 
$popularGroups = $query->getArrayResult(); 

GÜNCELLEME: Fiili sınıfları görmeden kolay değil

/** 
* Entity\E_User 
* 
* @ORM\Table(name="users") 
* @ORM\Entity 
*/ 
class E_User 
{ 
    /** 
    * @ORM\ManyToMany(targetEntity="E_Group", cascade={"persist"}) 
    * @ORM\JoinTable(name="users_groups", 
    *  joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="cascade")}, 
    *  inverseJoinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id", onDelete="cascade")} 
    *) 
    */ 

    protected $groups; 

    /** 
    * @var integer $id 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

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

    /* ... other attributes & getters and setters ...*/ 
} 


/** 
* Entity\E_Group 
* 
* @ORM\Table(name="groups") 
* @ORM\Entity 
*/ 
class E_Group 
{ 
    /** 
    * @var integer $id 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var string $name 
    * 
    * @ORM\Column(name="text", type="string", length=255) 
    */ 
    private $name; 

    /* ... other attributes & getters and setters ...*/ 
} 

cevap

6

ama teşekkür tahmin ederek bir sayıda çoğa çift yönlü bir ilişki var:

, çift yönlü bir ilişki kullanamazsınız; Doktrin en QueryBuilder yerine DQL doğrudan bu çözümü almak kullanmanın ile sorgu oluşturmak isteyenler için

$dql = "SELECT g.id, count(u.id) as cnt FROM Entity\User u " . 
    "JOIN u.groups g GROUP BY g.id ORDER BY cnt DESC LIMIT 10;"; 
+0

teşekkürler, sorun, Grup öğesinin kullanıcı adı verilen bir ilişkilendirmesi olmamasıdır. Bu yüzden istisnayı alıyorum: [Semantical Error] satırı 0, 's GROUP BY g.id' yakınındaki col 72: Hata: Class Entity \ E_Group adlı kullanıcının adlı bir ilişkilendirmesi yok. Soruyu asıl derslerle güncelledim. İki yönlü çoktan ilişki kurmak için E_Group öğesine $ users özniteliği ekleyeyim mi? –

+0

çok teşekkürler. Her neyse, iki yönlü bir ilişkiye girdim. Bu nasıl çalıştığını anlamak için sadece kukla bir soruydu. Tekrar teşekkürler –

0

: tersi ery.

Sorunumun en iyi kullanıcı gruplarını almamasına dikkat etmeliyim, ancak teknik olarak sorun benimkine benzer. Yayınlarla (makaleler/blog gönderileri gibi) ve yayınlara eklenen etiketlerle çalışıyorum. İlgili yazıların bir listesini (aynı etiketlerle tanımlanmış) belirlemem gerekiyordu. Bu listenin alaka düzeyine göre sıralanması gerekiyordu (başka bir gönderinin daha fazla etiketinin daha alakalı olması).

/** 
* Finds all related posts sorted by relavance 
* (from most important to least important) using 
* the tags of the given post entity. 
* 
* @param Post $post 
* 
* @return POST[] 
*/ 
public function findRelatedPosts(Post $post) { 
    // build query 
    $q = $this->createQueryBuilder('p') 
     ->addSelect('count(t.id) as relevance') 
     ->innerJoin('p.tags', 't') 
     ->where('t.id IN (:tags)') 
     ->setParameter('tags', $post->getTags()) 
     ->andWhere('p.id != :post') 
     ->setParameter('post', $post->getId()) 
     ->addGroupBy('p.id') 
     ->addOrderBy('relevance', 'DESC') 
     ->getQuery(); 

    // execute query and retrieve database result 
    $r = $q->execute(); 

    // result contains arrays, each array contains 
    // the actual post and the relevance value 
    // --> let's extract the post entities and 
    // forget about the relevance, because the 
    // posts are already sorted by relevance 
    $r = array_map(function ($entry) { 
     // first index is the post, second one 
     // is the relevance, just return the post 
     return reset($entry); 
    }, $r); 

    // array of posts 
    return $r; 
} 

size çözümü için size @Tom Imrei ederiz:

Bu

benim PostRepository sınıfının yöntemidir. Ayrıca #26549597 cevabı çok yardımcı oldu.