2 Module : Gargantext.Database.Flow
3 Description : Database Flow
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
12 {-# LANGUAGE QuasiQuotes #-}
13 -- {-# LANGUAGE Arrows #-}
15 module Gargantext.Database.Action.Flow.Pairing
20 import Control.Lens (_Just, (^.))
21 import Data.Map (Map, fromList, fromListWith)
22 import Data.Maybe (catMaybes, fromMaybe)
23 import Data.Text (Text, toLower)
24 import Database.PostgreSQL.Simple.SqlQQ (sql)
25 import Gargantext.Core.Types (TableResult(..))
26 import Gargantext.Database
27 import Gargantext.Database.Action.Flow.Utils
28 import Gargantext.Database.Admin.Types.Hyperdata -- (HyperdataContact(..))
29 import Gargantext.Database.Admin.Types.Node -- (AnnuaireId, CorpusId, ListId, DocId, ContactId, NodeId)
30 import Gargantext.Database.Prelude (Cmd, runPGSQuery)
31 import Gargantext.Database.Query.Table.Node.Children (getAllContacts)
32 import Gargantext.Database.Schema.Ngrams -- (NgramsType(..))
33 import Gargantext.Database.Schema.Node
34 import Gargantext.Prelude hiding (sum)
36 import qualified Data.List as List
37 import qualified Data.Map as DM
38 import qualified Data.Map as Map
39 import qualified Data.Text as DT
40 import qualified Data.Set as Set
42 -- TODO mv this type in Types Main
48 pairingPolicy :: (Terms -> Terms)
51 pairingPolicy f (NgramsT nt (Ngrams ng _)) = (NgramsT nt (Ngrams (f ng) 1))
54 pairMaps :: Map (NgramsT Ngrams) a
55 -> Map (NgramsT Ngrams) NgramsId
56 -> Map NgramsIndexed (Map NgramsType a)
59 [ (NgramsIndexed ng nId, DM.singleton nt n2i)
60 | (k@(NgramsT nt ng),n2i) <- DM.toList m1
61 , Just nId <- [DM.lookup k m2]
65 -----------------------------------------------------------------------
67 pairing :: AnnuaireId -> CorpusId -> ListId -> Cmd err Int
69 dataPaired <- dataPairing a (c,l,Authors) lastName toLower
70 insertDB $ prepareInsert dataPaired
73 dataPairing :: AnnuaireId
74 -> (CorpusId, ListId, NgramsType)
75 -> (ContactName -> Projected)
76 -> (DocAuthor -> Projected)
77 -> Cmd err (Map ContactId (Set DocId))
78 dataPairing aId (cId, lId, ngt) fc fa = do
79 mc <- getNgramsContactId aId
80 md <- getNgramsDocId cId lId ngt
83 from = projectionFrom (Set.fromList $ Map.keys mc) fc
84 to = projectionTo (Set.fromList $ Map.keys md) fa
86 pure $ fusion mc $ align from to md
90 prepareInsert :: Map ContactId (Set DocId) -> [NodeNode]
91 prepareInsert m = map (\(n1,n2) -> NodeNode n1 n2 Nothing Nothing)
93 $ map (\(contactId, setDocIds)
95 -> (contactId, setDocId)
96 ) $ Set.toList setDocIds
102 ------------------------------------------------------------------------
103 type ContactName = Text
104 type DocAuthor = Text
105 type Projected = Text
107 projectionFrom :: Set ContactName -> (ContactName -> Projected) -> Map ContactName Projected
108 projectionFrom ss f = fromList $ map (\s -> (s, f s)) (Set.toList ss)
110 projectionTo :: Set DocAuthor -> (DocAuthor -> Projected) -> Map Projected (Set DocAuthor)
111 projectionTo ss f = fromListWith (<>) $ map (\s -> (f s, Set.singleton s)) (Set.toList ss)
113 ------------------------------------------------------------------------
114 lastName :: Terms -> Terms
115 lastName texte = DT.toLower
116 $ maybe texte (\x -> if DT.length x > 3 then x else texte)
119 lastName' = lastMay . DT.splitOn " "
122 ------------------------------------------------------------------------
123 align :: Map ContactName Projected
124 -> Map Projected (Set DocAuthor)
125 -> Map DocAuthor (Set DocId)
126 -> Map ContactName (Set DocId)
127 align mc ma md = fromListWith (<>)
128 $ map (\c -> (c, getProjection md $ testProjection c mc ma))
131 getProjection :: Map DocAuthor (Set DocId) -> Set DocAuthor -> Set DocId
132 getProjection ma' sa' =
135 else Set.unions $ sets ma' sa'
137 sets ma'' sa'' = Set.map (\s -> lookup s ma'') sa''
138 lookup s' ma''= fromMaybe Set.empty (Map.lookup s' ma'')
140 testProjection :: ContactName
141 -> Map ContactName Projected
142 -> Map Projected (Set DocAuthor)
144 testProjection cn' mc' ma' = case Map.lookup cn' mc' of
146 Just c -> case Map.lookup c ma' of
151 fusion :: Map ContactName (Set ContactId)
152 -> Map ContactName (Set DocId)
153 -> Map ContactId (Set DocId)
154 fusion mc md = undefined
157 $ map (\c -> case Map.lookup c mc of
163 ------------------------------------------------------------------------
165 getNgramsContactId :: AnnuaireId
166 -> Cmd err (Map ContactName (Set NodeId))
167 getNgramsContactId aId = do
168 contacts <- getAllContacts aId
169 pure $ fromListWith (<>)
171 $ map (\contact -> (,) <$> contact^.(node_hyperdata . hc_who . _Just . cw_lastName)
172 <*> Just ( Set.singleton (contact^.node_id))
176 -- filter Trash / map Authors
177 -- Indexing all ngramsType like Authors
178 getNgramsDocId :: CorpusId
181 -> Cmd err (Map DocAuthor (Set NodeId))
182 getNgramsDocId corpusId listId ngramsType
184 <$> map (\(t,nId) -> (t, Set.singleton (NodeId nId)))
185 <$> selectNgramsDocId corpusId listId ngramsType
188 selectNgramsDocId :: CorpusId
191 -> Cmd err [(Text, Int)]
192 selectNgramsDocId corpusId' listId' ngramsType' =
193 runPGSQuery selectQuery (corpusId', listId', ngramsTypeId ngramsType')
195 selectQuery = [sql| SELECT ng.terms,nnng.node2_id from ngrams ng
196 JOIN node_node_ngrams nnng ON nnng.ngrams_id = ng.id
197 JOIN nodes_nodes nn ON nn.node2_id = nnng.node2_id
199 WHERE nn.node1_id = ?
200 AND nnng.node1_id = ?
201 AND nnng.ngrams_type = ?