Haskell 从Esqueleto'LeftOuterJoin返回'Maybe(实体a)``

Haskell 从Esqueleto'LeftOuterJoin返回'Maybe(实体a)``,haskell,yesod,persistent,esqueleto,Haskell,Yesod,Persistent,Esqueleto,从脚手架站点中的人工config/models: Inventory name Text description Text Container name Text ContainerSlot container ContainerId item InventoryId Maybe 现在,使用Esqueleto,我想使用LeftOuterJoin获取容器中的插槽,如果未分配实际库存,则实际库存为空 selectContainerS

从脚手架站点中的人工
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 :: Entity ContainerSlot -> Entity Inventory -> Result
Inventory
字段被
NULL
值填充时(可以预见),会导致运行时失败

PersistMarshalError "field id: int64 Expected Integer, received: PersistNull"

是否有办法将
实体清单
投影为
可能(实体清单)

这可能被标记为的副本;然而,不同之处在于投影

在处理任何外部联接时,所有可能返回null的表都应该使用
语法进行所有投影。
语法。这将迫使表的实体变成
Maybe(实体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
然后,应使用以下语法投影
i
is
(库存SKU表):

  on $ i ?. InventoryId ==. is ?. InventorySkuItem
  on $ cs ^. ContainerSlotItem ==. i ?. InventoryId
select $ from $ \(cs `LeftOuterJoin` (i `InnerJoin` is)) -> do
  on $ i ?. InventoryId ==. is ?. InventorySkuItem
  on $ cs ^. ContainerSlotItem ==. i ?. InventoryId