来自脚手架网站中的人为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
由于联接的“外部”性质,我希望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)
?
答案 0 :(得分:1)
这可能被标记为Outer Joins with Esqueleto的副本;但不同之处在于预测。
在处理任何外连接时,所有可能返回null的表都应该使用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
所以上面的解决方案是
select $ from $ \(cs `LeftOuterJoin` (i `InnerJoin` is)) -> do
此外,如果链接了多个表; e.g。
i
然后 is
和 on $ i ?. InventoryId ==. is ?. InventorySkuItem
on $ cs ^. ContainerSlotItem ==. i ?. InventoryId
(库存SKU表)应使用该语法进行投影:
Route::any('/home/createuser/{id}','HomeController@createuser');