hasbolt-extras 0.0.0.15 → 0.0.0.16
raw patch · 6 files changed
+85/−67 lines, 6 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Database.Bolt.Extras.Graph: GetRequestA :: GetRequestA
- Database.Bolt.Extras.Graph: GetRequestB :: GetRequestB
- Database.Bolt.Extras.Graph: PutRequestB :: PutRequestB
- Database.Bolt.Extras.Graph: data GetRequestA
- Database.Bolt.Extras.Graph: data GetRequestB
- Database.Bolt.Extras.Graph: data PutRequestB
- Database.Bolt.Extras.Graph: type GraphGetResponseA = Graph NodeName NodeResult RelResult
- Database.Bolt.Extras.Graph: type GraphGetResponseB = Graph NodeName Node URelationship
+ Database.Bolt.Extras.Graph: GetRequest :: GetRequest
+ Database.Bolt.Extras.Graph: PutRequest :: PutRequest
+ Database.Bolt.Extras.Graph: data GetRequest
+ Database.Bolt.Extras.Graph: data PutRequest
+ Database.Bolt.Extras.Graph: extractNode :: NodeLike a => NodeName -> GraphGetResponse -> a
+ Database.Bolt.Extras.Graph: extractNodeAeson :: NodeName -> GraphGetResponse -> NodeResult
+ Database.Bolt.Extras.Graph: extractNodeId :: NodeName -> GraphGetResponse -> BoltId
+ Database.Bolt.Extras.Graph: extractRelation :: URelationLike a => NodeName -> NodeName -> GraphGetResponse -> a
+ Database.Bolt.Extras.Graph: extractRelationAeson :: NodeName -> NodeName -> GraphGetResponse -> RelResult
+ Database.Bolt.Extras.Graph: extractRelationId :: NodeName -> NodeName -> GraphGetResponse -> BoltId
+ Database.Bolt.Extras.Graph: type GraphGetResponse = Graph NodeName NodeResult RelResult
Files
- CHANGELOG.md +4/−0
- example/Main.hs +5/−6
- hasbolt-extras.cabal +1/−1
- src/Database/Bolt/Extras/Graph/Internal/Get.hs +50/−26
- src/Database/Bolt/Extras/Graph/Internal/GraphQuery.hs +19/−33
- src/Database/Bolt/Extras/Internal/Instances.hs +6/−1
CHANGELOG.md view
@@ -6,6 +6,10 @@ ## [Unreleased] +## [0.0.0.16] - 2019-02-01+### Changed+- Optimized query, easy way to extract entities from result graph.+ ## [0.0.0.15] - 2019-01-22 ### Changed - Ability to choose whether to return entity or not in graphs.
example/Main.hs view
@@ -11,7 +11,6 @@ import Data.Aeson (encode) import qualified Data.ByteString.Lazy.Char8 as B (putStrLn) import Data.Default (def)-import Data.Map.Strict ((!)) import Data.Text (Text) import Database.Bolt (BoltActionT, BoltCfg (..), Value (..), close, connect, run)@@ -105,7 +104,7 @@ -- putGraph :: IO () putGraph = do- putGraphR <- runQueryDB $ makeRequest @PutRequestB [] examplePutGraph+ putGraphR <- runQueryDB $ makeRequest @PutRequest [] examplePutGraph putStrLn "Uploaded graph: " print putGraphR @@ -113,8 +112,8 @@ -- getGraphB :: IO () getGraphB = do- getGraphsR <- runQueryDB $ makeRequest @GetRequestB [] exampleGetGraphB- let nodesA :: [ExampleNode] = fromNode . (! exNodeAVar) . _vertices <$> getGraphsR+ getGraphsR <- runQueryDB $ makeRequest @GetRequest [] exampleGetGraphB+ let nodesA :: [ExampleNode] = extractNode exNodeAVar <$> getGraphsR putStrLn "Downloaded graph and converted to Haskell object: " print nodesA @@ -122,8 +121,8 @@ -- getGraphA :: IO () getGraphA = do- getGraphsR <- runQueryDB $ makeRequest @GetRequestA [] exampleGetGraphA- let nodesA = (! exNodeAVar) . _vertices <$> getGraphsR+ getGraphsR <- runQueryDB $ makeRequest @GetRequest [] exampleGetGraphA+ let nodesA = extractNodeAeson exNodeAVar <$> getGraphsR putStrLn "Downloaded graph and converted to JSON: " B.putStrLn . encode $ nodesA
hasbolt-extras.cabal view
@@ -1,5 +1,5 @@ name: hasbolt-extras-version: 0.0.0.15+version: 0.0.0.16 synopsis: Extras for hasbolt library description: Extras for hasbolt library homepage: https://github.com/biocad/hasbolt-extras#readme
src/Database/Bolt/Extras/Graph/Internal/Get.hs view
@@ -6,7 +6,6 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-} {-# LANGUAGE ViewPatterns #-} {-# OPTIONS_GHC -fno-warn-orphans #-} @@ -31,10 +30,18 @@ , relationName -- * Graph types , GraphGetRequest- , GraphGetResponseA- , GraphGetResponseB+ , GraphGetResponse+ -- * Helpers to extract entities from result graph+ , extractNode+ , extractRelation+ , extractNodeId+ , extractRelationId+ , extractNodeAeson+ , extractRelationAeson ) where +import Control.Lens (at, non, to,+ (^.)) import Control.Monad.IO.Class (MonadIO) import Data.Aeson as A (FromJSON (..), Result (..),@@ -60,7 +67,8 @@ import Data.Monoid ((<>)) import Data.Text (Text, cons, intercalate,- pack)+ pack,+ unpack) import Database.Bolt as B (BoltActionT, Node (..), Record,@@ -73,7 +81,9 @@ URelationLike (..)) import Database.Bolt.Extras.Graph.Internal.AbstractGraph (Graph, NodeName,- relationName)+ relationName,+ relations,+ vertices) import Database.Bolt.Extras.Graph.Internal.Class (Extractable (..), Requestable (..), Returnable (..))@@ -217,8 +227,6 @@ -- RESULT -- ---------------------------------------------------------- --- | AESON FORMAT- -- | Result for node in the Aeson like format. -- data NodeResult = NodeResult { nresId :: BoltId@@ -261,17 +269,6 @@ instance Extractable RelResult where extract = extractFromJSON -------------------------------------------------------------- | BOLT FORMAT--instance Extractable Node where- extract :: forall m. MonadIO m => Text -> [Record] -> BoltActionT m [Node]- extract t rec = fmap toNode <$> extractFromJSON @ _ @ NodeResult t rec--instance Extractable URelationship where- extract :: forall m. MonadIO m => Text -> [Record] -> BoltActionT m [URelationship]- extract t rec = fmap toURelation <$> extractFromJSON @ _ @ RelResult t rec- extractFromJSON :: (MonadIO m, FromJSON a) => Text -> [Record] -> BoltActionT m [a] extractFromJSON var = pure . fmap (\r -> case fromJSON (toJSON (r ! var)) of Success parsed -> parsed@@ -290,19 +287,46 @@ fromURelation URelationship{..} = RelResult urelIdentity urelType (toJSON <$> urelProps) ------------------------------------------------------------- GRAPH TYPES --+-- GRAPH -- ---------------------------------------------------------- -- | The combinations of 'Getter's to load graph from the database. -- type GraphGetRequest = Graph NodeName NodeGetter RelGetter --- | The graph of 'Node's and 'URelationship's which we got from the database using 'GraphGetRequest',--- converted to the Aeson Value like.+-- | The graph of 'Node's and 'URelationship's which we got from the database using 'GraphGetRequest'. ---type GraphGetResponseA = Graph NodeName NodeResult RelResult+type GraphGetResponse = Graph NodeName NodeResult RelResult --- | The graph of 'Node's and 'URelationship's which we got from the database using 'GraphGetRequest',--- converted to the Bolt Value like.----type GraphGetResponseB = Graph NodeName Node URelationship+-- | Some helpers to extract entities from the result graph.++extractNode :: NodeLike a => NodeName -> GraphGetResponse -> a+extractNode var graph = graph ^. vertices . at var . non (errorForNode var) . to (fromNode . toNode)++extractRelation :: URelationLike a => NodeName -> NodeName -> GraphGetResponse -> a+extractRelation stVar enVar graph = graph ^. relations . at (stVar, enVar)+ . non (errorForRelation stVar enVar)+ . to (fromURelation . toURelation)++extractNodeId :: NodeName -> GraphGetResponse -> BoltId+extractNodeId var graph = graph ^. vertices . at var . non (errorForNode var) . to nresId++extractRelationId :: NodeName -> NodeName -> GraphGetResponse -> BoltId+extractRelationId stVar enVar graph = graph ^. relations . at (stVar, enVar)+ . non (errorForRelation stVar enVar)+ . to rresId++extractNodeAeson :: NodeName -> GraphGetResponse -> NodeResult+extractNodeAeson var graph = graph ^. vertices . at var . non (errorForNode var)++extractRelationAeson :: NodeName -> NodeName -> GraphGetResponse -> RelResult+extractRelationAeson stVar enVar graph = graph ^. relations . at (stVar, enVar)+ . non (errorForRelation stVar enVar)++errorForNode :: NodeName -> a+errorForNode name = error . unpack $ "node with name " <> name <> " doesn't exist"++errorForRelation :: NodeName -> NodeName -> a+errorForRelation stName enName = error . unpack $ "relation between nodes " <>+ stName <> " and " <> enName <>+ " doesn't exist"
src/Database/Bolt/Extras/Graph/Internal/GraphQuery.hs view
@@ -11,9 +11,8 @@ module Database.Bolt.Extras.Graph.Internal.GraphQuery ( GraphQuery (..)- , GetRequestA (..)- , GetRequestB (..)- , PutRequestB (..)+ , GetRequest (..)+ , PutRequest (..) , mergeGraphs ) where @@ -30,9 +29,7 @@ null, pack) import Database.Bolt (BoltActionT,- Node, Record,- URelationship, query) import Database.Bolt.Extras (BoltId, GetBoltId (..)) import Database.Bolt.Extras.Graph.Internal.AbstractGraph (Graph (..),@@ -83,10 +80,12 @@ -> Text formQuery customConds graph = [text|$completeRequest $conditionsQ- RETURN DISTINCT $completeReturn|]+ WITH DISTINCT $distinctVars+ RETURN $completeReturn|] where vertices' = toList (graph ^. vertices) relations' = toList (graph ^. relations)+ distinctVars = intercalate ", " $ fmap fst vertices' ++ fmap (relationName . fst) relations' (completeRequest, reqConds) = requestEntities @a vertices' relations' @@ -134,29 +133,16 @@ -- GET -- --------------------------------------------------------------------------------------- --- | Get request with result in Aeson format.--- Easy way to show result graphs.----data GetRequestA = GetRequestA---- | Get request with result in Bolt format.--- Easy way to extract results and convert them to another entities (using 'fromNode').+-- | Get request with graph result. ---data GetRequestB = GetRequestB--instance GraphQuery GetRequestA where- type NodeReq GetRequestA = NodeGetter- type RelReq GetRequestA = RelGetter- type NodeRes GetRequestA = NodeResult- type RelRes GetRequestA = RelResult- requestEntities = requestGetters+data GetRequest = GetRequest -instance GraphQuery GetRequestB where- type NodeReq GetRequestB = NodeGetter- type RelReq GetRequestB = RelGetter- type NodeRes GetRequestB = Node- type RelRes GetRequestB = URelationship- requestEntities = requestGetters+instance GraphQuery GetRequest where+ type NodeReq GetRequest = NodeGetter+ type RelReq GetRequest = RelGetter+ type NodeRes GetRequest = NodeResult+ type RelRes GetRequest = RelResult+ requestEntities = requestGetters --------------------------------------------------------------------------------------- -- PUT --@@ -164,13 +150,13 @@ -- | Put request in Bolt format with 'BoltId's of uploaded entities as result. ---data PutRequestB = PutRequestB+data PutRequest = PutRequest -instance GraphQuery PutRequestB where- type NodeReq PutRequestB = PutNode- type RelReq PutRequestB = PutRelationship- type NodeRes PutRequestB = BoltId- type RelRes PutRequestB = BoltId+instance GraphQuery PutRequest where+ type NodeReq PutRequest = PutNode+ type RelReq PutRequest = PutRelationship+ type NodeRes PutRequest = BoltId+ type RelRes PutRequest = BoltId requestEntities = requestPut -- | Helper function to merge graphs of results, i.e.
src/Database/Bolt/Extras/Internal/Instances.hs view
@@ -11,9 +11,10 @@ import Data.Aeson.Types (Parser) import Data.Map.Strict (Map) import Data.Text (Text)-import Database.Bolt (Value (..))+import Database.Bolt (Node, Value (..)) import qualified Database.Bolt as DB (Structure) import Database.Bolt.Extras.Internal.Types (FromValue (..),+ NodeLike (..), ToValue (..)) import Database.Bolt.Extras.Utils (currentLoc) import GHC.Float (double2Float,@@ -115,3 +116,7 @@ <|> L <$> (parseJSON v :: Parser [Value]) <|> M <$> (parseJSON v :: Parser (Map Text Value)) <|> error "Database.Bolt.Extras.Internal.Instances: could not convert from json Database.Bolt.Value"++instance NodeLike Node where+ toNode = id+ fromNode = id