简体   繁体   中英

Haskell Persistent Joins with Esqueleto

I've been looking into the Persistent library to interface with sql databases. Suppose I have a database containing recipes, with Recipe, Ingredient, and RecIng tables.

My (admittedly limited) understanding of persistent leads me to believe I should define the tables like this:

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Recipe 
    title String
Ingredient 
    name String
RecIng
    recId RecipeId
    ingId IngredientId
    quantity Int
|]

With this, it is possible to use Esqueleto to get the inner join between these tables:

select $
from $ \(i `InnerJoin ` ri `InnerJoin` r) -> do
    on (r ^. RecipeId ==. ri ^. RecIngIngId)
    on (i ^. IngredientId ==. ri ^. RegIngRecId)
    return (r, ri, i)

This returns tuple of (Recipe, RecIng, Ingredient).

What I really want is a way to query recipes that results in the following:

data Recipe = Recipe { title :: String
                     , ingredients :: [Ingredient]
                     }

data Ingredient = Ingredient { name :: String
                             , quantity :: Integer
                             }

Other than defining an additional set of data types, and converting the tuples, is there a best practice for doing this kind of thing?

+1 to Adam's comment, it's the right answer IMO.

A separate approach you could take would be to use embedded entities, which would essentially mean JSON-encoding the list of ingredients into each recipe. But this would be bad SQL design, would cause table locking issues for updates, and wouldn't scale well for large numbers of ingredients.

In other words, there's a mismatch between the Haskell representation you want to work with and the right way to store the data in the database. This doesn't mean there's a problem with either your database format or your Haskell datatypes: it's a logical difference. The right response to this gap is to have two datatypes and an intelligent way to convert between them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM