7

tôi có một truy vấn lớn (trong trình tạo truy vấn của tôi) và nhiều lần tham gia trái. Vì vậy, tôi nhận được bài viết với ý kiến ​​và thẻ của họ và như vậy. Hãy nói rằng tôi có DQL sau:Doctrine2: Giới hạn với việc tham gia trái/phân trang - Thực hành tốt nhất

$dql = 'SELECT blogpost, comment, tags 
FROM BlogPost blogpost 
LEFT JOIN blogpost.comments comments 
LEFT JOIN blogpost.tags tags'; 

Bây giờ giả sử cơ sở dữ liệu của tôi có hơn 100 blogposts nhưng tôi chỉ muốn là người đầu tiên 10, nhưng với tất cả các ý kiến ​​của những người 10 và tất cả các thẻ của họ, nếu chúng tồn tại . Nếu tôi sử dụng setMaxResults, nó sẽ giới hạn hàng. Vì vậy, tôi có thể nhận được hai bài viết đầu tiên, nhưng bài cuối cùng trong số đó là thiếu một số nhận xét hoặc thẻ của nó. Vì vậy, followin không hoạt động.

$result = $em->createQuery($dql)->setMaxResults(15)->getResult(); 

Sử dụng hầu như không ghi nhận Pagination Giải pháp mà tàu với doctrine2.2 không thực sự làm việc cho tôi, hoặc vì nó là quá chậm, tôi có thể cũng tải tất cả các dữ liệu.

Tôi đã thử Giải pháp trong Stackoverflow Article, nhưng ngay cả Điều đó vẫn thiếu một Phương pháp hay nhất và Giải pháp được trình bày chậm chạp.

Không có phương pháp hay nhất về cách thực hiện việc này? Không ai sử dụng Doctrine2.2 trong chế độ Sản xuất?

+1

Vui lòng thêm mã bạn có vào câu hỏi của mình, thậm chí có thể có kết quả ví dụ để hiển thị những gì bạn muốn và những gì bạn đang nhận được. –

Trả lời

10

Nhận kết quả phù hợp với truy vấn như thế này là có vấn đề. Có một hướng dẫn trên trang web của Doctrine giải thích vấn đề này.

Pagination

Các hướng dẫn là thêm về pagination chứ không nhận được 5 kết quả hàng đầu, nhưng ý tưởng tổng thể là những gì bạn cần để làm một "SELECT DISTINCT a.id TỪ điều một ... LIMIT 5" thay vì của một SELECT bình thường. Nó phức tạp hơn một chút so với điều này, nhưng 2 điểm cuối cùng trong hướng dẫn đó sẽ giúp bạn đi đúng hướng.

Cập nhật:

Vấn đề ở đây không phải là Doctrine, hoặc bất kỳ ORM khác. Vấn đề nằm trên cơ sở dữ liệu có thể trả về kết quả bạn đang yêu cầu. Đây chỉ là cách tham gia làm việc.

Nếu bạn làm một GIẢI THÍCH về truy vấn, nó sẽ cung cấp cho bạn câu trả lời chi tiết hơn về những gì đang xảy ra. Sẽ là một ý kiến ​​hay khi thêm kết quả của câu hỏi đó vào câu hỏi ban đầu của bạn.

Xây dựng dựa trên những gì được thảo luận trong bài viết Phân trang, có vẻ như bạn cần ít nhất 2 truy vấn để có được kết quả mong muốn. Việc thêm DISTINCT vào một truy vấn có khả năng làm chậm đáng kể truy vấn của bạn, nhưng nó chỉ thực sự cần thiết nếu bạn đã tham gia vào nó. Bạn có thể viết một truy vấn khác mà chỉ cần truy xuất 10 bài đăng đầu tiên được sắp xếp theo ngày được tạo, mà không cần tham gia. Khi bạn có ID của 10 bài đăng đó, hãy thực hiện một truy vấn khác với các kết nối của bạn và WHERE blogpost.id IN (...) ORDER BY blogpost.created. Phương pháp này sẽ hiệu quả hơn nhiều.

SELECT 
    bp 
FROM 
    Blogpost bp 
ORDER BY 
    bp.created DESC 
LIMIT 10 

Vì tất cả những gì bạn quan tâm trong truy vấn đầu tiên là ID, bạn có thể đặt Doctrine sử dụng Scalar Hydration.

SELECT 
    bg 
FROM 
    Blogpost bp 
LEFT JOIN 
    bp.comments c 
LEFT JOIN 
    bp.tags t 
WHERE 
    bp.id IN (...) 
ORDER BY 
    bp.created DESC 

Bạn cũng có thể làm điều đó trong một truy vấn bằng cách sử dụng truy vấn con tương quan. Chuyện hoang đường rằng truy vấn phụ luôn xấu là KHÔNG đúng. Đôi khi chúng nhanh hơn tham gia. Bạn sẽ cần phải thử nghiệm để tìm ra giải pháp tốt nhất cho bạn.

2

Sửa trong ánh sáng của câu hỏi làm rõ:

Bạn có thể làm những gì bạn muốn trong MySQL có nguồn gốc sử dụng một subquery trong mệnh đề FROM như vậy:

SELECT * FROM 
(SELECT * FROM articles ORDER BY date LIMIT 5) AS limited_articles, 
comments, 
tags 
WHERE 
limited_articles.article_id=comments.article_id 
limited_articles.article_id=tags.article_id 

Theo như tôi biết, DQL không hỗ trợ các truy vấn phụ như thế này, vì vậy bạn có thể sử dụng lớp NativeQuery.

+0

Không, tôi không muốn M gần đây nhất của N. Tôi muốn N gần đây nhất với tất cả M, X và Y. –

+0

Tôi không phải là một fan hâm mộ lớn của việc sử dụng một khung DABL/ORM và sau đó vẫn còn sử dụng bản địa Truy vấn. Không có nhiều ý nghĩa với tôi. –

+1

Sau đó, có vẻ như bạn sẽ cần phải thực hiện hai truy vấn. Tôi đồng ý rằng nên có cách tốt hơn để giới hạn và kết quả trang của các kết nối. –

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