Saya memiliki tipe data yang didefinisikan sebagai:
data ComitteeView = CommitteeView { committeeId :: CommitteeId
, committeeMembers :: [Person]
}
data CommitteesView = CommitteesView { committeeView :: [CommitteeView] }
Sekarang, sebagaimana adanya, saya memiliki model Persisten yang didefinisikan sebagai:
Person
name Text
Committee
name Text
CommitteePerson
personId PersonId
committeeId CommitteeId
Saya dapat dengan mudah membuat kueri untuk mengisi CommitteeView, menggunakan Esqueleto. Ini akan seperti ini:
getCommitteeView cid =
CommitteeView <$> runDB $
select $
from (person `InnerJoin` pxc `InnerJoin` committee) -> do
on (committee ^. CommitteeId ==. pxc ^. CommitteePersonCommitteeId)
on (person ^. PersonId ==. pxc ^. CommitteePersonPersonId)
where_ (committee ^. CommitteePersonCommitteeId ==. val cid)
return person
Sekarang, pertimbangkan masalah mengisi CommitteesView
. Pada prinsipnya, kami mendapatkan data yang cukup untuk diisi dengan menjalankan subquery dalam kueri di atas. Oke, cukup adil. Sekarang bagaimana saya bisa menggunakan "group by Haskell-list" seperti group by
di SQL? Bagaimana saya bisa melipat baris sehingga saya bisa berakhir dengan daftar daftar orang?
Saya mendapat kesan yang esqueleto
tidak bisa menangani kasing seperti itu (yaitu, tidak memiliki kombinator yang akan melakukannya). Dan database dasar saya jelas tidak mendukung daftar Haskell sebagai kolom. Tapi, tentu saja, saya tidak bisa menjadi satu-satunya orang yang menghadapi masalah ini. Apa strategi yang efektif? Melipat daftar-n daftar menjadi daftar-n? Atau menjalankan n+1
kueri? Apakah ada opsi lain?
Data.List.groupBy
?Jawaban:
Esqueleto TIDAK dimaksudkan untuk menangani daftar sub daftar (daftar multidimensi) di luar kotak!
Data.List.groupBy
'cdk' yang disarankan untuk Anda hanya dapat mengelompokkan daftar sendiri, tetapi tidak apa yang Anda minta.Untuk kasus Anda, saya akan terus-menerus menyarankan Anda untuk menggunakan query SQL klasik. Anda dapat menjalankan n + 1 kueri, tetapi lakukan itu hanya jika itu jarang dan tidak dapat digunakan fungsinya, yang misalnya menyiapkan data yang di-cache (berdasarkan pada nama variabel Anda, saya kira itu mungkin tidak berat digunakan dan patut dicoba). Untuk penggunaan berat Anda harus mempertimbangkan menggunakan SQL klasik tanpa keraguan.
Jika Anda pergi ke https://github.com/prowdsponsor/esqueleto Anda akan menemukan bahwa:
sehingga Anda dapat mencoba untuk meminta fitur baru. Semoga berhasil!
sumber