Menangani jenis-Daftar dengan Esqueleto

144

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 bydi SQL? Bagaimana saya bisa melipat baris sehingga saya bisa berakhir dengan daftar daftar orang?

Saya mendapat kesan yang esqueletotidak 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+1kueri? Apakah ada opsi lain?

nomen
sumber
2
Sudahkah Anda melihat Data.List.groupBy?
cdk
@cdk: Ya, itulah yang saya lakukan. Tapi ternyata rambutnya sangat berbulu.
Nomen

Jawaban:

2

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:

Tidak semua fitur SQL tersedia, tetapi sebagian besar dapat dengan mudah ditambahkan (terutama fungsi).

sehingga Anda dapat mencoba untuk meminta fitur baru. Semoga berhasil!

Kainax
sumber
Apakah Anda memiliki tautan ke sumber tentang ini? Saya akan dengan senang hati memberikan hadiah jika seseorang dapat memverifikasi ini adalah jawaban yang benar atau Anda dapat memberikan semacam dokumentasi.
Tech Savant
@ NotoriousPet0 Jika Anda mengunjungi situs web haskell, Anda akan menemukan daftar lengkap contoh dan kasus penggunaan dan tidak ada yang menggunakan daftar multidimensi, bahkan "gabung dalam". Jika Anda mencari "grup oleh" di sana, Anda akan menemukan bahwa itu dapat digunakan untuk melampirkan beberapa kolom dalam tuple atau mengurutkan berdasarkan fungsi agregat tambahan. Dikatakan juga di sana bahwa pengembang mencoba membuat Esqueleto lebih fleksibel untuk mendukung permintaan apa pun, sehingga Anda dapat meminta ekstensi tambahan di sini .
Kainax