2012-12-27 25 views
5

Đối với một dự án tôi cần cung cấp cho một tải dữ liệu đa dạng ở định dạng JSON. Tất cả các thông tin sẽ được sử dụng trên cùng một trang để một cuộc gọi duy nhất sẽ dẫn đến chi phí thấp nhất. Thông tin tất cả đều liên quan đến cùng một đối tượng cơ sở dữ liệu và tất cả đều cần thiết trên trang. Về cơ bản nó là một tập hợp các số lượng các đối tượng có một hoặc nhiều loại nhất định (các kiểu là tất cả các phép toán) và chúng tôi yêu cầu phải biết nhiều biến thể khác nhau về điều này. Tôi đã sử dụng đoạn mã dưới đây nhưng đồng nghiệp của tôi tin rằng cách tôi đặt nó trong danh sách JSON hơi phức tạp và mã có thể có hiệu suất cao hơn. Làm thế nào tôi có thể cải thiện mã này?Nhiều COUNT truy vấn trên cùng một loại Thực thể bằng cách sử dụng Symfony 2.1 và Doctrine 2

public function getContactsStatisticsAction() 
{ 
    $response = new Response(); 
    $json = array(); 
    $em = $this->getDoctrine()->getEntityManager(); 
    $cr = $em->getRepository('BlaCoreBundle:Company'); 

    $json['numberOfCompanies'] = $cr->numberOfCompanies(); 
    $json['numberOfAccounts'] = $cr->numberOfCompanies(array("typeAccount" => true)); 
    $json['numberOfCompetitors'] = $cr->numberOfCompanies(array("typeCompetitor" => true)); 
    $json['numberOfSuppliers'] = $cr->numberOfCompanies(array("typeSupplier" => true)); 
    $json['numberOfOthers'] = $cr->numberOfCompanies(array("typeOther" => true)); 
    $json['numberOfUnassigned'] = $cr->numberOfCompanies(array("typeAccount" => false, "typeCompetitor" => false,"typeSupplier" => false,"typeOther" => false)); 

    $json['numberOfJustAccounts'] = $cr->numberOfCompanies(array("typeAccount" => true, "typeCompetitor" => false, "typeSupplier" => false)); 
    $json['numberOfJustCompetitors'] = $cr->numberOfCompanies(array("typeAccount" => false, "typeCompetitor" => false, "typeSupplier" => false)); 
    $json['numberOfJustSuppliers'] = $cr->numberOfCompanies(array("typeAccount" => false, "typeCompetitor" => false, "typeSupplier" => false)); 

    $json['numberOfCompetitorAndAccounts'] = $cr->numberOfCompanies(array("typeAccount" => true, "typeCompetitor" => true, "typeSupplier" => false)); 
    $json['numberOfCompetitorAndSuppliers'] = $cr->numberOfCompanies(array("typeAccount" => false, "typeCompetitor" => true, "typeSupplier" => true)); 
    $json['numberOfSupplierAndAccounts'] = $cr->numberOfCompanies(array("typeAccount" => true, "typeCompetitor" => false, "typeSupplier" => true)); 
    $json['numberOfCompaniesAndAccountsAndSuppliers'] = $cr->numberOfCompanies(array("typeAccount" => true, "typeCompetitor" => true, "typeSupplier" => true)); 

    $response->setContent(json_encode($json)); 
    return $response; 
} 


public function numberOfCompanies($filters = array()) 
{ 
    $qb = $this->getEntityManager()->createQueryBuilder(); 
    $qb->select('count(c.id)'); 
    $qb->from('BlaCoreBundle:Company', 'c'); 
    $sizeFilters = count ($filters); 
    $keys = array_keys($filters); 
    if($sizeFilters >= 1){ 
     $qb->where('c.' . $keys[0] . ' = ' . (int) $filters[$keys[0]]); 
    } 
    for($i = 1; $i < $sizeFilters; $i++){ 
     $qb->andWhere('c.' . $keys[$i] . ' = ' . (int) $filters[$keys[$i]]); 
    } 
    return $qb->getQuery()->getSingleScalarResult(); 
} 
+0

Tôi nghĩ điều này thuộc về http://codereview.stackexchange.com/. –

+0

Được rồi, tôi cũng sẽ đăng nó ở đó. Cảm ơn bạn! – Kristof

Trả lời

3

Đồng nghiệp của bạn đúng. Bạn sẽ nhận được tất cả các kết quả vô hướng trong một truy vấn. Bạn sẽ giảm thiểu số lượng kết nối theo cách này.

Chủ đề được giải quyết trong this answer đối với trường hợp không phải là Giáo lý.

Người dùng như vậy cũng đã đưa ra câu hỏi thú vị này here, nhưng không ai trả lời.

Thực ra tôi nghĩ rằng không có cách nào để giải quyết loại truy vấn này với QueryBuilder hoặc với DQL. Cũng trong tài liệu chính thức cho Doctrine2.2 không có ví dụ nào về số JOIN trên số SELECT.

giống như truy vấn DQL sau gì bạn có thể thử là:

return $this->getEntityManager()->createQuery(
    SELECT COUNT(c1) AS C1, COUNT(c2) AS C2, COUNT(c3) AS C3 FROM 
    BlaCoreBundle:Company c1, BlaCoreBundle:Company c2, BlaCoreBundle:Company c3 
    WHERE c1.prop1 = 'xxx' AND c2.prop2 > '100' AND c3.prop3 LIKE '%XYZ%')    
    ->getResult(); 

nơi tất nhiên các điều khoản ĐÂU là những ví dụ nói chung. Truy vấn này sẽ trả về một mảng có kích thước, với C1, C2 và C3 làm khóa cho các giá trị bạn đã đếm. Tất nhiên, sẽ khó sử dụng JOIN và bất cứ điều gì bạn cần, nhưng bạn luôn có thể sử dụng WHERE IN (SELECT...)WHERE EXISTS (SELECT...), ví dụ:

SELECT COUNT(c1) AS C1, COUNT(c2) AS C2, COUNT(c3) AS C3 FROM 
    BlaCoreBundle:Company c1, BlaCoreBundle:Company c2, BlaCoreBundle:Company c3 
    WHERE c1.prop1 = 'xxx' AND c2.prop2 > '100' AND c3.prop3 LIKE '%XYZ%' 
AND EXISTS (SELECT x FROM BlaCoreBundle:Entity x JOIN x.company comp WHERE x.prop = "valye" AND comp = c1)    
+0

Tôi đã thêm một giải pháp có thể! Tôi đã thử nó và hoạt động rất tốt. – JeanValjean

Các vấn đề liên quan