add associateJoin function

this helps avoid N+1 queries
This commit is contained in:
brady.ouren 2019-10-23 15:31:15 -07:00
parent 53515b868f
commit e94808856f
3 changed files with 27 additions and 1 deletions

View File

@ -47,6 +47,7 @@ library
, aeson >=1.0
, blaze-html
, bytestring
, containers >=0.6
, conduit >=1.3
, monad-logger
, persistent >=2.10.0 && <2.11

View File

@ -50,6 +50,7 @@ import qualified Data.ByteString as B
import qualified Data.Conduit as C
import qualified Data.Conduit.List as CL
import qualified Data.HashSet as HS
import qualified Data.Map.Strict as Map
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Builder as TLB
@ -2884,3 +2885,27 @@ insertSelect = void . insertSelectCount
insertSelectCount :: (MonadIO m, PersistEntity a) =>
SqlQuery (SqlExpr (Insertion a)) -> SqlWriteT m Int64
insertSelectCount = rawEsqueleto INSERT_INTO . fmap EInsertFinal
-- | Avoid N+1 queries and join entities into a map structure
-- @
-- getFoosAndNestedBarsFromParent :: ParentId -> (Map (Key Foo) (Foo, [Entity Bar]))
-- getFoosAndNestedBarsFromParent parentId = 'fmap' associateJoin $ 'select' $
-- 'from' $ \\(foo `'LeftOuterJoin`` bar) -> do
-- 'on' (bar '^.' BarFooId '==.' foo '^.' FooId)
-- 'where_' (foo '^.' FooParentId '==.' 'val' parentId)
-- 'pure' (foo, bar)
-- @
associateJoin
:: forall e1 e0
. Ord (Key e0)
=> [(Entity e0, e1)]
-> Map.Map (Key e0) (e0, [e1])
associateJoin = foldr f start
where
start = Map.empty
f (one, many) =
Map.insertWith
(\(oneOld, manyOld) (_, manyNew) -> (oneOld, manyNew ++ manyOld ))
(entityKey one)
(entityVal one, [many])

View File

@ -55,7 +55,7 @@ module Database.Esqueleto.Internal.Language
, subList_select, valList, justList
, in_, notIn, exists, notExists
, set, (=.), (+=.), (-=.), (*=.), (/=.)
, case_, toBaseId, (<#), (<&>)
, case_, toBaseId, (<#), (<&>), associateJoin
) where
import Database.Esqueleto.Internal.PersistentImport