2017-04-02 3 views
1

Von einem gekünstelt config/models in einer gerüst Website:Rückkehr `Vielleicht (a Entity)` von Esqueleto `LeftOuterJoin`

Inventory 
    name  Text 
    description Text 
Container 
    name  Text 
ContainerSlot 
    container ContainerId 
    item  InventoryId Maybe 

nun mit Esqueleto, ich will LeftOuterJoin verwenden, um die Schlitze in einem Behälter zu bekommen, Das tatsächliche Inventar ist leer, wenn es nicht zugewiesen wurde.

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 

Ich würde erwarten, buildStuff die folgende Signatur aufgrund der „äußeren“ Natur des müssen beitreten:

buildStuff :: Entity ContainerSlot -> Maybe (Entity Inventory) -> Result 

aber feststellen, dass es folgendes benötigt:

buildStuff :: Entity ContainerSlot -> Entity Inventory -> Result 

Welche verursacht Laufzeitfehler, wenn (vorhersehbar) dieFelder mit NULL Werten gefüllt sind.

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

Gibt es eine Möglichkeit, die Entity Inventory als Maybe (Entity Inventory) zu projizieren?

Antwort

1

Dies könnte wahrscheinlich ein Duplikat von Outer Joins with Esqueleto markiert werden; Der Unterschied liegt jedoch in der Projektion.

Beim Umgang mit Outer-Joins sollten alle Tabellen, die möglicherweise null zurückkommen, alle-Projektionen mit der ?.-Syntax haben. Dies wird die Tabellen Einheiten zwingen Maybe (Entity a) zu werden, so die Lösung des oben ist

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 

Außerdem, wenn mehr als eine Tabelle gekettet; z.B.

select $ from $ \(cs `LeftOuterJoin` (i `InnerJoin` is)) -> do 

Dann sowohli und is (Bestandstabelle SKU) sollte mit dieser Syntax projiziert werden:

on $ i ?. InventoryId ==. is ?. InventorySkuItem 
    on $ cs ^. ContainerSlotItem ==. i ?. InventoryId 
Verwandte Themen