Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
haskell-gargantext
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
153
Issues
153
List
Board
Labels
Milestones
Merge Requests
12
Merge Requests
12
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gargantext
haskell-gargantext
Commits
c7c1b188
Commit
c7c1b188
authored
Feb 22, 2018
by
Alexandre Delanoë
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[API/Count] Adding route and types.
parent
b0c08ab1
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
357 additions
and
40 deletions
+357
-40
gargantext.cabal
gargantext.cabal
+17
-15
package.yaml
package.yaml
+1
-0
API.hs
src/Gargantext/API.hs
+17
-2
Count.hs
src/Gargantext/API/Count.hs
+64
-0
Node.hs
src/Gargantext/API/Node.hs
+20
-20
Facet.hs
src/Gargantext/Database/Facet.hs
+162
-0
Queries.hs
src/Gargantext/Database/Queries.hs
+64
-0
stack.yaml
stack.yaml
+12
-3
No files found.
gargantext.cabal
View file @
c7c1b188
...
...
@@ -2,26 +2,27 @@
--
-- see: https://github.com/sol/hpack
--
-- hash:
20ddea403b5eab78aff204d088cc635422d7b9b34369ff1c4263e3ba67969442
-- hash:
3346e420cce910077cbb6172c7e942960a4edd72fbab96679d4b45dacd84dcd9
name:
gargantext
version:
0.1.0.0
synopsis:
Deep (Collaborative) Text mining project
description:
Please see README.md
homepage: https://gargantext.org
license: BSD3
license-file: LICENSE
author: Gargantext Team
maintainer: team@gargantext.org
copyright: Copyright: (c) 2017-2018: see git logs and README
category: Data
build-type:
Simple
cabal-version:
>= 1.10
name: gargantext
version: 0.1.0.0
synopsis: Deep (Collaborative) Text mining project
description: Please see README.md
category: Data
homepage: https://gargantext.org
author: Gargantext Team
maintainer: team@gargantext.org
copyright: Copyright: (c) 2017-2018: see git logs and README
license: BSD3
license-file: LICENSE
build-type: Simple
cabal-version: >= 1.10
library
hs-source-dirs:
src
default-extensions: NoImplicitPrelude
ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates -Werror
build-depends:
aeson
, aeson-lens
...
...
@@ -59,6 +60,7 @@ library
, servant
, servant-auth
, servant-client
, servant-mock
, servant-multipart
, servant-server
, split
...
...
@@ -114,12 +116,12 @@ library
Gargantext.Utils.DateUtils
Gargantext.Utils.Prefix
other-modules:
Gargantext.API.Count
Gargantext.API.Node
Gargantext.Database.Queries
Gargantext.Utils
Paths_gargantext
default-language: Haskell2010
ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates -Werror
executable gargantext
main-is: Main.hs
...
...
package.yaml
View file @
c7c1b188
...
...
@@ -90,6 +90,7 @@ library:
-
safe
-
semigroups
-
servant
-
servant-mock
-
servant-client
-
servant-multipart
-
servant-server
...
...
src/Gargantext/API.hs
View file @
c7c1b188
{-|
Module : Gargantext.
Server
Module : Gargantext.
API
Description : Server API
Copyright : (c) CNRS, 2017-Present
License : AGPL + CECILL v3
...
...
@@ -16,6 +16,7 @@ TODO/IDEA, use MOCK feature of Servant to generate fake data (for tests)
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DeriveGeneric #-}
module
Gargantext.API
where
...
...
@@ -24,16 +25,19 @@ import Gargantext.Prelude
import
Network.Wai
import
Network.Wai.Handler.Warp
import
Servant
-- import Servant.API.Stream
import
Database.PostgreSQL.Simple
(
Connection
,
connect
)
import
System.IO
(
FilePath
,
print
)
-- import Gargantext.API.Auth
import
Gargantext.API.Node
(
Roots
,
roots
,
NodeAPI
,
nodeAPI
,
NodesAPI
,
nodesAPI
)
import
Gargantext.API.Count
(
CountAPI
,
count
,
Query
)
import
Gargantext.Database.Utils
(
databaseParameters
)
...
...
@@ -50,9 +54,16 @@ startGargantext port file = do
-- | Main routes of the API are typed
type
API
=
"roots"
:>
Roots
:<|>
"node"
:>
Capture
"id"
Int
:>
NodeAPI
:<|>
"nodes"
:>
ReqBody
'[
J
SON
]
[
Int
]
:>
NodesAPI
:<|>
"count"
:>
ReqBody
'[
J
SON
]
Query
:>
CountAPI
-- :<|> "counts" :> Stream GET NewLineFraming '[JSON] Count :> CountAPI
-- /mv/<id>/<id>
-- /merge/<id>/<id>
-- /rename/<id>
-- :<|> "static"
-- :<|> "list" :> Capture "id" Int :> NodeAPI
-- :<|> "ngrams" :> Capture "id" Int :> NodeAPI
...
...
@@ -64,6 +75,10 @@ server :: Connection -> Server API
server
conn
=
roots
conn
:<|>
nodeAPI
conn
:<|>
nodesAPI
conn
:<|>
count
-- | TODO App type, the main monad in which the bot code is written with.
-- Provide config, state, logs and IO
...
...
src/Gargantext/API/Count.hs
0 → 100644
View file @
c7c1b188
{-|
Module : Gargantext.API.Count
Description : Server API
Copyright : (c) CNRS, 2017-Present
License : AGPL + CECILL v3
Maintainer : team@gargantext.org
Stability : experimental
Portability : POSIX
Count API part of Gargantext.
-}
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DeriveGeneric #-}
module
Gargantext.API.Count
where
import
Gargantext.Prelude
import
Data.Text
(
Text
,
pack
)
import
Servant
import
GHC.Generics
(
Generic
)
import
Data.Aeson
hiding
(
Error
)
type
CountAPI
=
Post
'[
J
SON
]
Count
data
Scraper
=
Pubmed
|
Hal
deriving
(
Generic
)
instance
FromJSON
Scraper
instance
ToJSON
Scraper
data
Query
=
Query
{
query_query
::
Text
,
query_name
::
Maybe
[
Scraper
]
}
deriving
(
Generic
)
instance
FromJSON
Query
instance
ToJSON
Query
data
Error
=
Error
{
error_message
::
Text
,
error_code
::
Int
}
deriving
(
Generic
)
instance
FromJSON
Error
instance
ToJSON
Error
data
Count
=
Count
{
count_name
::
Scraper
,
count_count
::
Maybe
Int
,
count_errors
::
Maybe
[
Error
]
}
deriving
(
Generic
)
instance
FromJSON
Count
instance
ToJSON
Count
count
::
Query
->
Handler
Count
count
_
=
pure
(
Count
Pubmed
(
Just
10
)
(
Just
[
Error
(
pack
"error message"
)
202
]))
src/Gargantext/API/Node.hs
View file @
c7c1b188
...
...
@@ -18,13 +18,13 @@ Node API
module
Gargantext.API.Node
where
import
Control.Monad
import
Control.Monad.IO.Class
(
liftIO
)
import
Data.Aeson
(
Value
())
import
Servant
import
Servant.Multipart
import
System.IO
(
putStrLn
,
readFile
)
import
Data.Text
(
Text
(),
pack
)
-- import Servant.Multipart
--import System.IO (putStrLn, readFile)
import
Data.Text
(
Text
())
--import Data.Text (Text(), pack)
import
Database.PostgreSQL.Simple
(
Connection
)
import
Gargantext.Prelude
import
Gargantext.Types.Main
(
Node
,
NodeId
,
NodeType
)
...
...
@@ -57,7 +57,7 @@ type NodeAPI = Get '[JSON] (Node Value)
-- Depending on the Type of the Node, we could post
-- New documents for a corpus
-- New map list terms
:<|>
"process"
:>
MultipartForm
MultipartData
:>
Post
'[
J
SON
]
Text
--
:<|> "process" :> MultipartForm MultipartData :> Post '[JSON] Text
-- To launch a query and update the corpus
:<|>
"query"
:>
Capture
"string"
Text
:>
Get
'[
J
SON
]
Text
...
...
@@ -73,7 +73,7 @@ nodeAPI conn id = liftIO (getNode conn id)
:<|>
deleteNode'
conn
id
:<|>
getNodesWith'
conn
id
:<|>
getDocFacet'
conn
id
:<|>
upload
--
:<|> upload
:<|>
query
nodesAPI
::
Connection
->
[
NodeId
]
->
Server
NodesAPI
...
...
@@ -99,18 +99,18 @@ query s = pure s
-- | Upload files
-- TODO Is it possible to adapt the function according to iValue input ?
upload
::
MultipartData
->
Handler
Text
upload
multipartData
=
do
liftIO
$
do
putStrLn
"Inputs:"
forM_
(
inputs
multipartData
)
$
\
input
->
putStrLn
$
" "
<>
show
(
iName
input
)
<>
" -> "
<>
show
(
iValue
input
)
forM_
(
files
multipartData
)
$
\
file
->
do
content
<-
readFile
(
fdFilePath
file
)
putStrLn
$
"Content of "
<>
show
(
fdFileName
file
)
<>
" at "
<>
fdFilePath
file
putStrLn
content
pure
(
pack
"Data loaded"
)
--
upload :: MultipartData -> Handler Text
--
upload multipartData = do
--
liftIO $ do
--
putStrLn "Inputs:"
--
forM_ (inputs multipartData) $ \input ->
--
putStrLn $ " " <> show (iName input)
--
<> " -> " <> show (iValue input)
--
--
forM_ (files multipartData) $ \file -> do
--
content <- readFile (fdFilePath file)
--
putStrLn $ "Content of " <> show (fdFileName file)
--
<> " at " <> fdFilePath file
--
putStrLn content
--
pure (pack "Data loaded")
src/Gargantext/Database/Facet.hs
0 → 100644
View file @
c7c1b188
{-|
Module : Gargantext.Database.Facet
Description : Main requests of Node to the database
Copyright : (c) CNRS, 2017-Present
License : AGPL + CECILL v3
Maintainer : team@gargantext.org
Stability : experimental
Portability : POSIX
-}
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE Arrows #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module
Gargantext.Database.Facet
where
import
Prelude
hiding
(
null
,
id
,
map
,
sum
,
not
)
import
Gargantext.Types
import
Gargantext.Types.Main
(
NodeType
)
import
Gargantext.Database.NodeNode
import
Gargantext.Database.NodeNodeNgram
import
Gargantext.Database.Node
import
Gargantext.Database.Queries
import
Gargantext.Utils.Prefix
(
unPrefix
)
-- import Gargantext.Database.NodeNgram
-- import Data.Aeson (Value)
import
Data.Aeson.TH
(
deriveJSON
)
import
Control.Arrow
(
returnA
)
import
Control.Lens.TH
(
makeLensesWith
,
abbreviatedFields
)
import
Data.Maybe
(
Maybe
)
import
Data.Profunctor.Product.TH
(
makeAdaptorAndInstance
)
import
Data.Time
(
UTCTime
)
import
Database.PostgreSQL.Simple
(
Connection
)
import
Opaleye
import
Opaleye.Internal.Join
(
NullMaker
)
import
qualified
Opaleye.Internal.Unpackspec
()
import
Data.Profunctor.Product.Default
(
Default
)
-- DocFacet
type
FacetDoc
=
Facet
NodeId
UTCTime
HyperdataDocument
Bool
-- Double
data
Facet
id
created
hyperdata
favorite
=
FacetDoc
{
facetDoc_id
::
id
,
facetDoc_created
::
created
,
facetDoc_hyperdata
::
hyperdata
,
facetDoc_favorite
::
favorite
-- To be added: Double
-- , facetDoc_ngramCount :: ngramCount
}
deriving
(
Show
)
$
(
deriveJSON
(
unPrefix
"facetDoc_"
)
''
F
acet
)
-- Facets / Views for the Front End
type
FacetDocRead
=
Facet
(
Column
PGInt4
)
(
Column
PGTimestamptz
)
(
Column
PGJsonb
)
(
Column
PGBool
)
-- (Column PGFloat8)
$
(
makeAdaptorAndInstance
"pFacetDoc"
''
F
acet
)
$
(
makeLensesWith
abbreviatedFields
''
F
acet
)
getDocFacet
::
Connection
->
Int
->
Maybe
NodeType
->
Maybe
Offset
->
Maybe
Limit
->
IO
[
FacetDoc
]
getDocFacet
conn
parentId
nodeType
maybeOffset
maybeLimit
=
runQuery
conn
$
selectDocFacet
parentId
nodeType
maybeOffset
maybeLimit
selectDocFacet
::
ParentId
->
Maybe
NodeType
->
Maybe
Offset
->
Maybe
Limit
->
Query
FacetDocRead
selectDocFacet
parentId
maybeNodeType
maybeOffset
maybeLimit
=
limit'
maybeLimit
$
offset'
maybeOffset
$
orderBy
(
asc
facetDoc_created
)
$
selectDocFacet'
parentId
maybeNodeType
-- | Left join to the favorites
nodeNodeLeftJoin
::
Query
(
NodeRead
,
NodeNodeReadNull
)
nodeNodeLeftJoin
=
leftJoin
queryNodeTable
queryNodeNodeTable
(
eqNode
)
where
eqNode
(
Node
n1
_
_
_
_
_
_
,
NodeNode
_
n2
_
)
=
((
.==
)
n1
n2
)
nodeNodeLeftJoin'
::
(
Column
(
Nullable
PGInt4
))
->
Query
(
NodeRead
,
NodeNodeReadNull
)
nodeNodeLeftJoin'
nId
=
leftJoin
queryNodeTable
queryNodeNodeTable
(
eqNode
nId
)
where
eqNode
n
(
Node
n1
_
_
_
_
_
_
,
NodeNode
n1'
n2
_
)
=
foldl
(
.&&
)
(
pgBool
True
)
[
((
.==
)
n1
n2
)
,
((
.==
)
n1'
n
)
]
nodeNodeLeftJoin''
::
Query
(
NodeRead
,
NodeRead
,
NodeNodeRead
)
nodeNodeLeftJoin''
=
join3
queryNodeTable
queryNodeTable
queryNodeNodeTable
eqNode
where
eqNode
(
Node
n1
_
_
_
_
_
_
,
Node
n2
_
_
_
_
_
_
,
NodeNode
n1'
n2'
_
)
=
foldl
(
.&&
)
(
pgBool
True
)
[
((
.==
)
n2
n2'
)
,
((
.==
)
(
toNullable
n1
)
n1'
)
]
-- | Left join to the ngram count per document
nodeNodeNgramLeftJoin
::
Query
(
NodeRead
,
NodeNodeNgramReadNull
)
nodeNodeNgramLeftJoin
=
leftJoin
queryNodeTable
queryNodeNodeNgramTable
(
eqNode
)
where
eqNode
(
Node
n1
_
_
_
_
_
_
,
NodeNodeNgram
n1'
_
_
_
)
=
((
.==
)
n1
n1'
)
nodeNodeNgramLeftJoin'
::
Column
(
Nullable
PGInt4
)
->
Query
(
NodeRead
,
NodeNodeNgramReadNull
)
nodeNodeNgramLeftJoin'
nId
=
leftJoin
queryNodeTable
queryNodeNodeNgramTable
(
eqNode
nId
)
where
eqNode
nId'
(
Node
n1
_
_
_
_
_
_
,
NodeNodeNgram
n1'
n2
_
_
)
=
(
.&&
)
((
.==
)
n1
n1'
)
((
.==
)
nId'
(
toNullable
n2
))
leftJoin3
::
(
Default
NullMaker
(
columnsL1
,
nullableColumnsR
)
nullableColumnsR1
,
Default
NullMaker
columnsR
nullableColumnsR
,
Default
Unpackspec
columnsR
columnsR
,
Default
Unpackspec
nullableColumnsR
nullableColumnsR
,
Default
Unpackspec
columnsL1
columnsL1
,
Default
Unpackspec
columnsL
columnsL
)
=>
Query
columnsL1
->
Query
columnsR
->
Query
columnsL
->
((
columnsL1
,
columnsR
)
->
Column
PGBool
)
->
((
columnsL
,
(
columnsL1
,
nullableColumnsR
))
->
Column
PGBool
)
->
Query
(
columnsL
,
nullableColumnsR1
)
leftJoin3
q1
q2
q3
cond12
cond23
=
leftJoin
q3
(
leftJoin
q1
q2
cond12
)
cond23
-- | Building the facet
selectDocFacet'
::
ParentId
->
Maybe
NodeType
->
Query
FacetDocRead
selectDocFacet'
parentId
_
=
proc
()
->
do
node
<-
(
proc
()
->
do
-- Favorite Column
(
Node
_
favTypeId
_
favParentId
_
_
_
)
<-
queryNodeTable
-<
()
restrict
-<
favTypeId
.==
15
.&&
favParentId
.==
(
toNullable
$
pgInt4
parentId
)
-- select nn.score from nodes n left join nodes_nodes nn on n.id = nn.node2_id where n.typename =4;
-- Selecting the documents and joining Favorite Node
(
Node
docId
docTypeId
_
docParentId
_
created
docHyperdata
,
NodeNode
_
docTypeId'
_
)
<-
nodeNodeLeftJoin'
(
toNullable
$
pgInt4
347537
)
-<
()
restrict
-<
docParentId
.==
(
toNullable
$
pgInt4
parentId
)
let
docTypeId''
=
maybe
0
nodeTypeId
(
Just
Document
)
restrict
-<
if
docTypeId''
>
0
then
docTypeId
.==
(
pgInt4
(
docTypeId''
::
Int
))
else
(
pgBool
True
)
-- Getting favorite data
let
isFav
=
ifThenElse
(
isNull
docTypeId'
)
(
pgBool
False
)
(
pgBool
True
)
-- Ngram count by document
-- Counting the ngram
-- (Node occId occTypeId _ _ _ _ _, NodeNode _ _ _ count) <- nodeNodeNgramLeftJoin -< ()
-- restrict -< occId .== 347540
--returnA -< (FacetDoc n_id hyperdata isFav ngramCount)) -< ()
returnA
-<
(
FacetDoc
docId
created
docHyperdata
isFav
))
-<
()
returnA
-<
node
src/Gargantext/Database/Queries.hs
0 → 100644
View file @
c7c1b188
{-|
Module : Gargantext.Database.Queries
Description : Main requests of Node to the database
Copyright : (c) CNRS, 2017-Present
License : AGPL + CECILL v3
Maintainer : team@gargantext.org
Stability : experimental
Portability : POSIX
-}
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE Arrows #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module
Gargantext.Database.Queries
where
import
Gargantext.Prelude
import
Gargantext.Types
(
Limit
,
Offset
,
NodePoly
)
import
Data.Maybe
(
Maybe
,
maybe
)
import
Control.Arrow
((
>>>
))
import
Control.Applicative
((
<*>
))
import
Opaleye
-- (Query, limit, offset)
type
NodeWrite
=
NodePoly
(
Maybe
(
Column
PGInt4
))
(
Column
PGInt4
)
(
Column
PGInt4
)
(
Column
(
Nullable
PGInt4
))
(
Column
(
PGText
))
(
Maybe
(
Column
PGTimestamptz
))
(
Column
PGJsonb
)
-- (Maybe (Column PGTSVector))
type
NodeRead
=
NodePoly
(
Column
PGInt4
)
(
Column
PGInt4
)
(
Column
PGInt4
)
(
Column
(
Nullable
PGInt4
))
(
Column
(
PGText
))
(
Column
PGTimestamptz
)
(
Column
PGJsonb
)
-- (Column PGTSVector)
join3
::
Query
columnsA
->
Query
columnsB
->
Query
columnsC
->
((
columnsA
,
columnsB
,
columnsC
)
->
Column
PGBool
)
->
Query
(
columnsA
,
columnsB
,
columnsC
)
join3
q1
q2
q3
cond
=
((,,)
<$>
q1
<*>
q2
<*>
q3
)
>>>
keepWhen
cond
--leftJoin3 :: Query columnsL1 -> Query columnsR -> Query columnsL
-- -> ((columnsL1, columnsR) -> Column PGBool)
-- -> ((columnsL, (columnsL1, nullableColumnsR1)) -> Column PGBool)
-- -> Query (columnsL, nullableColumnsR)
--leftJoin3 q1 q2 q3 cond12 cond23 = leftJoin q3 (leftJoin q1 q2 cond12) cond23
limit'
::
Maybe
Limit
->
Query
a
->
Query
a
limit'
maybeLimit
query
=
maybe
query
(
\
l
->
limit
l
query
)
maybeLimit
offset'
::
Maybe
Offset
->
Query
a
->
Query
a
offset'
maybeOffset
query
=
maybe
query
(
\
o
->
offset
o
query
)
maybeOffset
stack.yaml
View file @
c7c1b188
...
...
@@ -2,12 +2,21 @@ flags: {}
extra-package-dbs
:
[]
packages
:
-
.
#- /home/alexandre/local/logiciels/haskell/servant/servant-multipart
#- /home/alexandre/local/logiciels/haskell/utc
extra-deps
:
-
aeson-1.0.2.1
-
attoparsec-0.13.2.2
-
duckling-0.1.3.0
-
http-media-0.7.1.2
-
http-types-0.11
-
mmorph-1.1.0
-
protolude-0.2
-
servant-
multipart-0.10.0
.1
-
servant-
0.12
.1
-
servant-auth-0.3.0.1
-
servant-client-0.12.0.1
-
servant-client-core-0.12
-
servant-docs-0.11.1
-
servant-mock-0.8.3
-
servant-multipart-0.11.1
-
servant-server-0.12
-
text-1.2.3.0
resolver
:
lts-9.2
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment