从 Esqueleto `LeftOuterJoin` 返回 `Maybe (Entity a)`
Returning `Maybe (Entity a)` from Esqueleto `LeftOuterJoin`
来自脚手架网站中人为的 config/models
:
Inventory
name Text
description Text
Container
name Text
ContainerSlot
container ContainerId
item InventoryId Maybe
现在,使用 Esqueleto,我想使用 LeftOuterJoin
获取容器中的插槽,如果尚未分配,则实际库存为空。
selectContainerSlots containerKey = do
stuff <- select $ from $ \(cs `LeftOuterJoin` i) -> do
on $ cs ^. ContainerSlotItem ==. just (i ^. InventoryId)
where_ $ cs ^. ContainerSlotContainer ==. val containerKey
return (cs, i)
return $ uncurry buildStuff <$> stuff
由于连接的 "outer" 性质,我希望 buildStuff
需要以下签名:
buildStuff :: Entity ContainerSlot -> Maybe (Entity Inventory) -> Result
但发现它需要以下内容:
buildStuff :: Entity ContainerSlot -> Entity Inventory -> Result
当 Inventory
字段填充 NULL
值时(可以预见)会导致运行时失败。
PersistMarshalError "field id: int64 Expected Integer, received: PersistNull"
有没有办法将 Entity Inventory
投影为 Maybe (Entity Inventory)
?
这可能被标记为 Outer Joins with Esqueleto 的重复;然而不同之处在于投影。
在处理任何外部联接时,所有可能返回 null 的 table 都应该使用 ?.
语法完成 all 投影。这将迫使 table 的实体变成 Maybe (Entity a)
所以上面的解决方案是
selectContainerSlots containerKey = do
stuff <- select $ from $ \(cs `LeftOuterJoin` i) -> do
on $ cs ^. ContainerSlotItem ==. i ?. InventoryId
where_ $ cs ^. ContainerSlotContainer ==. val containerKey
return (cs, i)
return $ uncurry buildStuff <$> stuff
此外,如果链接了多个 table;例如
select $ from $ \(cs `LeftOuterJoin` (i `InnerJoin` is)) -> do
然后 i
和 is
(库存 SKU table)应该使用该语法进行投影:
on $ i ?. InventoryId ==. is ?. InventorySkuItem
on $ cs ^. ContainerSlotItem ==. i ?. InventoryId
来自脚手架网站中人为的 config/models
:
Inventory
name Text
description Text
Container
name Text
ContainerSlot
container ContainerId
item InventoryId Maybe
现在,使用 Esqueleto,我想使用 LeftOuterJoin
获取容器中的插槽,如果尚未分配,则实际库存为空。
selectContainerSlots containerKey = do
stuff <- select $ from $ \(cs `LeftOuterJoin` i) -> do
on $ cs ^. ContainerSlotItem ==. just (i ^. InventoryId)
where_ $ cs ^. ContainerSlotContainer ==. val containerKey
return (cs, i)
return $ uncurry buildStuff <$> stuff
由于连接的 "outer" 性质,我希望 buildStuff
需要以下签名:
buildStuff :: Entity ContainerSlot -> Maybe (Entity Inventory) -> Result
但发现它需要以下内容:
buildStuff :: Entity ContainerSlot -> Entity Inventory -> Result
当 Inventory
字段填充 NULL
值时(可以预见)会导致运行时失败。
PersistMarshalError "field id: int64 Expected Integer, received: PersistNull"
有没有办法将 Entity Inventory
投影为 Maybe (Entity Inventory)
?
这可能被标记为 Outer Joins with Esqueleto 的重复;然而不同之处在于投影。
在处理任何外部联接时,所有可能返回 null 的 table 都应该使用 ?.
语法完成 all 投影。这将迫使 table 的实体变成 Maybe (Entity a)
所以上面的解决方案是
selectContainerSlots containerKey = do
stuff <- select $ from $ \(cs `LeftOuterJoin` i) -> do
on $ cs ^. ContainerSlotItem ==. i ?. InventoryId
where_ $ cs ^. ContainerSlotContainer ==. val containerKey
return (cs, i)
return $ uncurry buildStuff <$> stuff
此外,如果链接了多个 table;例如
select $ from $ \(cs `LeftOuterJoin` (i `InnerJoin` is)) -> do
然后 i
和 is
(库存 SKU table)应该使用该语法进行投影:
on $ i ?. InventoryId ==. is ?. InventorySkuItem
on $ cs ^. ContainerSlotItem ==. i ?. InventoryId