回答

收藏

Haskell持久加入Esqueleto

技术问答 技术问答 248 人阅读 | 0 人回复 | 2023-09-13

我一直在研究与SQL数据库接口的Persistent库。假设我有一个包含配方,配方,成分和RecIng表的数据库。
# }6 I% r) I2 _# H; F我对持久性的理解(绝对有限)使我相信我应该定义如下表:( z7 }1 k. E- }+ }# i/ r+ c: A
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
, x* k) [3 g3 A0 Y5 N. kRecipe
+ u7 W: B7 Y1 ^, d& d1 N  i9 r    title String
: g; u4 L* c3 q# R6 H# fIngredient
$ a  L- I0 ]/ Z/ D3 ~6 a) n    name String
) Z" r+ D3 }+ P/ Q, `& FRecIng
3 D+ ?7 @. Q) i) e6 p    recId RecipeId% Y; H) o# t+ r4 b# P6 {. F" ?
    ingId IngredientId* ~  w+ a( [3 y$ d5 {
    quantity Int
4 W* G1 C6 J4 s, y! B|]2 Q5 w! c- r% Z& t- j# t
这样,可以使用Esqueleto获取这些表之间的内部联接:
1 ~; m* |9 @' |4 M7 j' a% X( n. `select $
! B( ?% p+ q7 b$ }: |8 q0 L% Vfrom $ \(i `InnerJoin ` ri `InnerJoin` r) -> do
- P* P( b* [4 b1 H" a$ J- J    on (r ^. RecipeId ==. ri ^. RecIngIngId)
& O. s' h9 @3 Z" S: ^    on (i ^. IngredientId ==. ri ^. RegIngRecId)- Y" _. X( s. Y! a' g7 _1 H
    return (r, ri, i)2 U/ _! k/ I* b; c8 k5 \5 @
这将返回(Recipe,RecIng,Ingredient)的元组。
5 i+ }. ]5 @$ ?2 i3 o我真正想要的是一种查询配方的方法,其结果如下:
5 G( K0 |# e% x% u* qdata Recipe = Recipe { title :: String9 d+ q# N& E: x0 G
                     , ingredients :: [Ingredient]0 w) ]& C. K* s+ v" J
                     }- j6 [+ D2 Z3 P) j7 J$ |
data Ingredient = Ingredient { name :: String
. q4 s9 K# d* ~( `! q                             , quantity :: Integer
' p2 G8 e" z7 d9 J& k                             }
. S% }, C1 R! K$ d; `3 Q除了定义一组额外的数据类型并转换元组之外,是否有进行此类操作的最佳实践?
+ k5 Z7 S8 `( L: J; `               
# T6 F' J# p3 V) C+ @$ Y: s解决方案:/ I, x2 t4 O  H$ o7 H: @
                ' o8 x3 l) g6 i0 \/ u; ~" }* _

& u$ C* \, A1 _5 C+ l, h  A* m5 |
+ _/ M" _* ~9 J5 A                +1对亚当的评论,这是IMO的正确答案。" ]: G1 V! E$ a, `
您 可以/ b! t/ f- Q/ y1 h& a
采用的另一种方法是使用嵌入式实体,这实际上意味着将JSON编码成每个配方中的成分列表。但这将是不好的SQL设计,将导致表锁定问题以进行更新,并且无法很好地扩展大量成分。
$ R) _: Q. W( \5 P- q% H3 ?. v4 K3 k8 c换句话说,您要使用的Haskell表示形式与将数据存储在数据库中的正确方法之间不匹配。这并不意味着您的数据库格式或Haskell数据类型都存在问题:这是逻辑上的区别。应对这种差距的正确方法是拥有两种数据类型,以及在两种数据类型之间进行转换的明智方式。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则