2015-06-01 22 views
14

Về cơ bản, cùng một câu hỏi đã được hỏi về một năm trước cho slick 2.x (scala slick one-to-many collections). Tôi tự hỏi nếu có bất kỳ tiến triển nào được thực hiện với việc phát hành của slick phản ứng.Slick 3.0.0: Cách truy vấn quan hệ một-nhiều/nhiều-nhiều-nhiều

Ví dụ: chúng tôi có ba bảng. library, booklibrary_to_book nơi thư viện có nhiều sách. Những gì tôi muốn là một danh sách các thư viện với sách của họ. Trong scala này sẽ là một cái gì đó giống như Seq[(Library, Seq[Book])]. Các truy vấn tôi có là như sau:

val q = (for { 
    l <- libraries 
    ltb <- libraryToBooks if l.id === ltb.libraryId 
    b <- books if ltb.bookId === b.id 
} yield (l, b) 
db.run(q.result).map(result => ???) 

results trong trường hợp này là loại Seq[(Library, Book)]. Làm cách nào để thay đổi truy vấn của tôi để nhận được kết quả của loại Seq[(Library, Seq[Book])] thay thế? Cách "khéo léo" của việc viết các truy vấn như vậy là gì?

Trả lời

7

IMO mã của bạn có vẻ ổn. Nó thực sự phụ thuộc vào những gì cảm thấy dễ đọc hơn cho bạn. Ngoài ra, bạn có thể sử dụng tham gia cũng như:

val findBooksQuery = libraries 
    .join(libraryToBooks).on(_.id === _.libraryId) 
    .join(books).on(_.id === _._2.bookId) 
    .result 

val action = (for { 
    booksResult <- findBooksQuery 
} yield { 
    booksResult.map { row => 
    val (libraryTableRow, libraryToBooksTableRow) = row._1 
    val booksTableRow = row._2 
    // TODO: Access all data from the rows and construct desired DS 
    } 
} 

db.run(action) 

Sau đó bạn có thể làm một groupby trên một phím đặc biệt để có được những loại cấu trúc dữ liệu mà bạn đang tìm kiếm. Trong trường hợp này, nó sẽ được phát triển hơn vì nó tham gia trên ba bảng. Ví dụ, thêm sau vào truy vấn của bạn:

val findBooksQuery = libraries 
    .join(libraryToBooks).on(_.id === _.libraryId) 
    .join(books).on(_.id === _._2.bookId) 
    // To group by libraries.id 
    .groupBy(_._1.id) 
    .result 
+0

Như Sky đã đề cập trước đó trong một bình luận, không có cách nào để làm điều này trong slick atm. Tôi đoán phương pháp '.groupBy' mà bạn đề xuất là cách để đi ngay bây giờ. – Roman

+0

@Roman Điều này có trả lại một 'Seq' trống nếu một thư viện không có bất kỳ cuốn sách nào không? Nếu vậy, nó có thể không hoàn toàn phù hợp với kỳ vọng. – acjay

+0

@acjay: Trong trường hợp đó, điều này dẫn đến một 'Seq' trống rỗng. Nếu bạn muốn có tất cả các thư viện trong kết quả của bạn không có vấn đề nếu họ có sách hay không bạn có thể sử dụng tham gia bên ngoài thay vì tham gia bên trong ('joinLeft',' joinRight' trong điều khoản trơn). Cảm thấy tự do để mở một câu hỏi tiếp theo nếu đây không phải là những gì bạn đang tìm kiếm :) – Roman

0

Với những gì bạn muốn ánh xạ tới, db.run trả về Tương lai (về thứ gì đó), Tương lai [Seq [(Thư viện, Seq [Sách])]] trong trường hợp của bạn. Khi lập bản đồ trong tương lai bạn có quyền truy cập vào Seq và bạn có thể chuyển đổi nó thành một thứ khác để có được một Tương lai mới.

+0

Cảm ơn câu trả lời của bạn. Thật không may đây không phải là những gì tôi đang tìm kiếm. Tôi vừa cập nhật câu hỏi của mình và cố gắng cụ thể hơn một chút. – Roman

+2

@Roman Ngay bây giờ, không có cách nào để làm điều này trong Slick. – Sky

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