diff --git a/src/Gargantext/API.hs b/src/Gargantext/API.hs index d2bea33cdfc53245f48811f5035971618cc8eef2..dcd1069c8b501a641f0ac6d7d5104856fd9c904d 100644 --- a/src/Gargantext/API.hs +++ b/src/Gargantext/API.hs @@ -266,7 +266,8 @@ type GargPrivateAPI' = :> ReqBody '[JSON] Query :> CountAPI -- Corpus endpoint --> TODO rename s/search/filter/g - :<|> "search":> Capture "corpus" NodeId :> SearchPairsAPI + :<|> "search":> Capture "corpus" NodeId + :> SearchPairsAPI -- TODO move to NodeAPI? :<|> "graph" :> Summary "Graph endpoint" diff --git a/src/Gargantext/API/Node.hs b/src/Gargantext/API/Node.hs index 614fbaa114bb8eb0b56ac08aa4e654b8753f9601..8f5cf841b4e1e8337050385c28e38e4ddbbf7196 100644 --- a/src/Gargantext/API/Node.hs +++ b/src/Gargantext/API/Node.hs @@ -131,7 +131,7 @@ type NodeAPI a = Get '[JSON] (Node a) -- TODO gather it :<|> "table" :> TableApi :<|> "ngrams" :> TableNgramsApi - :<|> "pairing" :> PairingApi + -- :<|> "pairing" :> PairingApi :<|> "category" :> CatApi :<|> "search" :> SearchDocsAPI @@ -187,7 +187,7 @@ nodeAPI p uId id = withAccess (Proxy :: Proxy (NodeAPI a)) Proxy uId (PathNode i -- TODO gather it :<|> tableApi id :<|> apiNgramsTableCorpus id - :<|> getPairing id + -- :<|> getPairing id -- :<|> getTableNgramsDoc id :<|> catApi id diff --git a/src/Gargantext/API/Search.hs b/src/Gargantext/API/Search.hs index 15f341cfa205360379edc038ffa95a825f748038..c391ebc13a2f176360811ccf111e3d6e052647fb 100644 --- a/src/Gargantext/API/Search.hs +++ b/src/Gargantext/API/Search.hs @@ -65,7 +65,8 @@ instance Arbitrary SearchDocResults where instance ToSchema SearchDocResults where declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "sdr_") -data SearchPairedResults = SearchPairedResults { spr_results :: [FacetPaired Int UTCTime HyperdataDocument Int [Pair Int Text]] } +data SearchPairedResults = + SearchPairedResults { spr_results :: [FacetPaired Int UTCTime HyperdataDocument Int [Pair Int Text]] } deriving (Generic) $(deriveJSON (unPrefix "spr_") ''SearchPairedResults) @@ -87,12 +88,14 @@ type SearchAPI results :> Post '[JSON] results type SearchDocsAPI = SearchAPI SearchDocResults -type SearchPairsAPI = SearchAPI SearchPairedResults +type SearchPairsAPI = + Summary "" :> "list" :> Capture "list" ListId + :> SearchAPI SearchPairedResults ----------------------------------------------------------------------- searchPairs :: NodeId -> GargServer SearchPairsAPI -searchPairs pId (SearchQuery q) o l order = - SearchPairedResults <$> searchInCorpusWithContacts pId q o l order +searchPairs pId lId (SearchQuery q) o l order = + SearchPairedResults <$> searchInCorpusWithContacts pId lId q o l order searchDocs :: NodeId -> GargServer SearchDocsAPI searchDocs nId (SearchQuery q) o l order = diff --git a/src/Gargantext/API/Table.hs b/src/Gargantext/API/Table.hs index e0948db5e44d6123006650d7b6fcf988a7e79281..c12778b682df9f25e6600aebe6932176361dad63 100644 --- a/src/Gargantext/API/Table.hs +++ b/src/Gargantext/API/Table.hs @@ -46,7 +46,7 @@ import GHC.Generics (Generic) import Gargantext.API.Ngrams (TabType(..)) import Gargantext.Core.Types (Offset, Limit) import Gargantext.Core.Utils.Prefix (unPrefix, unPrefixSwagger) -import Gargantext.Database.Facet (FacetDoc , runViewDocuments, OrderBy(..),runViewAuthorsDoc) +import Gargantext.Database.Facet (FacetDoc , runViewDocuments, OrderBy(..)) import Gargantext.Database.Learn (FavOrTrash(..), moreLike) import Gargantext.Database.TextSearch import Gargantext.Database.Types.Node @@ -97,6 +97,7 @@ getTable cId ft o l order = (Just MoreTrash) -> moreLike cId o l order IsTrash x -> panic $ "not implemented in getTable: " <> (cs $ show x) +{- getPairing :: ContactId -> Maybe TabType -> Maybe Offset -> Maybe Limit -> Maybe OrderBy -> Cmd err [FacetDoc] @@ -106,4 +107,4 @@ getPairing cId ft o l order = (Just Trash) -> runViewAuthorsDoc cId True o l order _ -> panic $ "not implemented: get Pairing" <> (cs $ show ft) - +-} diff --git a/src/Gargantext/Database/Facet.hs b/src/Gargantext/Database/Facet.hs index a1cfa87792002c8bf6eed2e828da87b0dc5ab466..14d5d36e86299144eb8d5bb04a877c10ec6a6eea 100644 --- a/src/Gargantext/Database/Facet.hs +++ b/src/Gargantext/Database/Facet.hs @@ -26,8 +26,8 @@ Portability : POSIX {-# LANGUAGE TypeFamilies #-} ------------------------------------------------------------------------ module Gargantext.Database.Facet - ( runViewAuthorsDoc - , runViewDocuments + ( -- runViewAuthorsDoc + runViewDocuments , filterWith , Pair(..) @@ -41,6 +41,7 @@ module Gargantext.Database.Facet where ------------------------------------------------------------------------ import Control.Arrow (returnA) +import Control.Lens ((^.)) -- import Control.Lens.TH (makeLensesWith, abbreviatedFields) import Data.Aeson (FromJSON, ToJSON) import Data.Aeson.TH (deriveJSON) @@ -57,7 +58,6 @@ import Gargantext.Core.Utils.Prefix (unPrefix, unPrefixSwagger) import Gargantext.Database.Config (nodeTypeId) import Gargantext.Database.Schema.Ngrams import Gargantext.Database.Schema.Node -import Gargantext.Database.Schema.NodeNgram import Gargantext.Database.Schema.NodeNode import Gargantext.Database.Utils import Gargantext.Database.Queries.Join @@ -115,36 +115,39 @@ instance (ToSchema i, ToSchema l) => ToSchema (Pair i l) where instance (Arbitrary i, Arbitrary l) => Arbitrary (Pair i l) where arbitrary = Pair <$> arbitrary <*> arbitrary -data FacetPaired id date hyperdata score pairs = +data FacetPaired id date hyperdata score pair = FacetPaired {_fp_id :: id ,_fp_date :: date ,_fp_hyperdata :: hyperdata ,_fp_score :: score - ,_fp_pairs :: pairs + ,_fp_pair :: pair } deriving (Show, Generic) $(deriveJSON (unPrefix "_fp_") ''FacetPaired) $(makeAdaptorAndInstance "pFacetPaired" ''FacetPaired) -instance (ToSchema id, ToSchema date, ToSchema hyperdata, ToSchema pairs, ToSchema score) => ToSchema (FacetPaired id date hyperdata score pairs) where +instance ( ToSchema id + , ToSchema date + , ToSchema hyperdata + , ToSchema score + , ToSchema pair + ) => ToSchema (FacetPaired id date hyperdata score pair) where declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "_fp_") instance ( Arbitrary id , Arbitrary date , Arbitrary hyperdata , Arbitrary score - , Arbitrary pairs - ) => Arbitrary (FacetPaired id date hyperdata score pairs) where + , Arbitrary pair + ) => Arbitrary (FacetPaired id date hyperdata score pair) where arbitrary = FacetPaired <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary ---{- type FacetPairedRead = FacetPaired (Column PGInt4 ) (Column PGTimestamptz) (Column PGJsonb ) (Column PGInt4 ) - (Pair (Column (Nullable PGInt4)) (Column (Nullable PGText))) ---} - - + ( Column (Nullable PGInt4) + , Column (Nullable PGText) + ) -- | JSON instance $(deriveJSON (unPrefix "facetDoc_") ''Facet) @@ -206,6 +209,8 @@ instance Arbitrary OrderBy -- TODO-SECURITY check + +{- runViewAuthorsDoc :: ContactId -> IsTrash -> Maybe Offset -> Maybe Limit -> Maybe OrderBy -> Cmd err [FacetDoc] runViewAuthorsDoc cId t o l order = runOpaQuery $ filterWith o l order $ viewAuthorsDoc cId t ntId where @@ -234,16 +239,16 @@ queryAuthorsDoc = leftJoin5 queryNodeTable queryNodeNgramTable queryNgramsTable .== nng_node_id nodeNgram cond23 :: (NgramsRead, (NodeNgramRead, NodeReadNull)) -> Column PGBool - cond23 (ngrams, (nodeNgram, _)) = ngrams_id ngrams + cond23 (ngrams, (nodeNgram, _)) = ngrams^.ngrams_id .== nng_ngrams_id nodeNgram - + cond34 :: (NodeNgramRead, (NgramsRead, (NodeNgramReadNull, NodeReadNull))) -> Column PGBool - cond34 (nodeNgram2, (ngrams, (_,_)))= ngrams_id ngrams .== nng_ngrams_id nodeNgram2 - + cond34 (nodeNgram2, (ngrams, (_,_)))= ngrams^.ngrams_id .== nng_ngrams_id nodeNgram2 + cond45 :: (NodeRead, (NodeNgramRead, (NgramsReadNull, (NodeNgramReadNull, NodeReadNull)))) -> Column PGBool cond45 (contact, (nodeNgram2, (_, (_,_)))) = _node_id contact .== nng_node_id nodeNgram2 - +-} ------------------------------------------------------------------------ -- TODO-SECURITY check @@ -257,12 +262,12 @@ viewDocuments :: CorpusId -> IsTrash -> NodeTypeId -> Query FacetDocRead viewDocuments cId t ntId = proc () -> do n <- queryNodeTable -< () nn <- queryNodeNodeTable -< () - restrict -< _node_id n .== nn_node2_id nn - restrict -< nn_node1_id nn .== (pgNodeId cId) - restrict -< _node_typename n .== (pgInt4 ntId) - restrict -< if t then nn_category nn .== (pgInt4 0) - else nn_category nn .>= (pgInt4 1) - returnA -< FacetDoc (_node_id n) (_node_date n) (_node_name n) (_node_hyperdata n) (toNullable $ nn_category nn) (toNullable $ nn_score nn) + restrict -< n^.node_id .== nn^.nn_node2_id + restrict -< nn^.nn_node1_id .== (pgNodeId cId) + restrict -< n^.node_typename .== (pgInt4 ntId) + restrict -< if t then nn^.nn_category .== (pgInt4 0) + else nn^.nn_category .>= (pgInt4 1) + returnA -< FacetDoc (_node_id n) (_node_date n) (_node_name n) (_node_hyperdata n) (toNullable $ nn^.nn_category) (toNullable $ nn^.nn_score) ------------------------------------------------------------------------ diff --git a/src/Gargantext/Database/Flow.hs b/src/Gargantext/Database/Flow.hs index a495cbd1db0b32737d42ec527f67659196f69d07..14bae2d3b8da50aec1af65de3dd5bc30be1157dc 100644 --- a/src/Gargantext/Database/Flow.hs +++ b/src/Gargantext/Database/Flow.hs @@ -7,15 +7,12 @@ Maintainer : team@gargantext.org Stability : experimental Portability : POSIX - -- TODO-ACCESS: -- check userId CanFillUserCorpus userCorpusId -- check masterUserId CanFillMasterCorpus masterCorpusId -- TODO-ACCESS: check uId CanInsertDoc pId && checkDocType nodeType -- TODO-EVENTS: InsertedNodes - - -} {-# OPTIONS_GHC -fno-warn-orphans #-} @@ -109,29 +106,32 @@ getDataApi lang limit (ApiIsidoreAuth q) = Isidore.get lang limit Nothing (Jus -- UNUSED _flowCorpusApi :: ( FlowCmdM env err m) - => Username -> Either CorpusName [CorpusId] - -> TermType Lang - -> Maybe Limit - -> ApiQuery - -> m CorpusId + => Username -> Either CorpusName [CorpusId] + -> TermType Lang + -> Maybe Limit + -> ApiQuery + -> m CorpusId _flowCorpusApi u n tt l q = do docs <- liftIO $ splitEvery 500 <$> getDataApi (_tt_lang tt) l q flowCorpus u n tt docs ------------------------------------------------------------------------ --- UNUSED flowAnnuaire :: FlowCmdM env err m - => Username -> Either CorpusName [CorpusId] -> (TermType Lang) -> FilePath -> m AnnuaireId + => Username + -> Either CorpusName [CorpusId] + -> (TermType Lang) + -> FilePath + -> m AnnuaireId flowAnnuaire u n l filePath = do docs <- liftIO $ (( splitEvery 500 <$> deserialiseImtUsersFromFile filePath) :: IO [[HyperdataContact]]) flow (Nothing :: Maybe HyperdataAnnuaire) u n l docs -- UNUSED _flowCorpusDebat :: FlowCmdM env err m - => Username -> Either CorpusName [CorpusId] - -> Limit -> FilePath - -> m CorpusId + => Username -> Either CorpusName [CorpusId] + -> Limit -> FilePath + -> m CorpusId _flowCorpusDebat u n l fp = do docs <- liftIO ( splitEvery 500 <$> take l @@ -154,18 +154,30 @@ flowCorpusFile u n l la ff fp = do -- TODO query with complex query flowCorpusSearchInDatabase :: FlowCmdM env err m - => Username -> Lang -> Text -> m CorpusId + => Username + -> Lang + -> Text + -> m CorpusId flowCorpusSearchInDatabase u la q = do - (_masterUserId, _masterRootId, cId) <- getOrMkRootWithCorpus userMaster (Left "") (Nothing :: Maybe HyperdataCorpus) + (_masterUserId, _masterRootId, cId) <- getOrMkRootWithCorpus + userMaster + (Left "") + (Nothing :: Maybe HyperdataCorpus) ids <- map fst <$> searchInDatabase cId (stemIt q) flowCorpusUser la u (Left q) (Nothing :: Maybe HyperdataCorpus) ids -- UNUSED _flowCorpusSearchInDatabaseApi :: FlowCmdM env err m - => Username -> Lang -> Text -> m CorpusId + => Username + -> Lang + -> Text + -> m CorpusId _flowCorpusSearchInDatabaseApi u la q = do - (_masterUserId, _masterRootId, cId) <- getOrMkRootWithCorpus userMaster (Left "") (Nothing :: Maybe HyperdataCorpus) + (_masterUserId, _masterRootId, cId) <- getOrMkRootWithCorpus + userMaster + (Left "") + (Nothing :: Maybe HyperdataCorpus) ids <- map fst <$> searchInDatabase cId (stemIt q) flowCorpusUser la u (Left q) (Nothing :: Maybe HyperdataCorpus) ids @@ -178,20 +190,33 @@ data CorpusInfo = CorpusName Lang Text | CorpusId Lang NodeId -} - flow :: (FlowCmdM env err m, FlowCorpus a, MkCorpus c) - => Maybe c -> Username -> Either CorpusName [CorpusId] -> TermType Lang -> [[a]] -> m CorpusId + => Maybe c + -> Username + -> Either CorpusName [CorpusId] + -> TermType Lang + -> [[a]] + -> m CorpusId flow c u cn la docs = do ids <- mapM (insertMasterDocs c la ) docs flowCorpusUser (la ^. tt_lang) u cn c (concat ids) flowCorpus :: (FlowCmdM env err m, FlowCorpus a) - => Username -> Either CorpusName [CorpusId] -> TermType Lang -> [[a]] -> m CorpusId + => Username + -> Either CorpusName [CorpusId] + -> TermType Lang + -> [[a]] + -> m CorpusId flowCorpus = flow (Nothing :: Maybe HyperdataCorpus) ------------------------------------------------------------------------ flowCorpusUser :: (FlowCmdM env err m, MkCorpus c) - => Lang -> Username -> Either CorpusName [CorpusId] -> Maybe c -> [NodeId] -> m CorpusId + => Lang + -> Username + -> Either CorpusName [CorpusId] + -> Maybe c + -> [NodeId] + -> m CorpusId flowCorpusUser l userName corpusName ctype ids = do -- User Flow (userId, _rootId, userCorpusId) <- getOrMkRootWithCorpus userName corpusName ctype @@ -223,7 +248,10 @@ insertMasterDocs :: ( FlowCmdM env err m , FlowCorpus a , MkCorpus c ) - => Maybe c -> TermType Lang -> [a] -> m [DocId] + => Maybe c + -> TermType Lang + -> [a] + -> m [DocId] insertMasterDocs c lang hs = do (masterUserId, _, masterCorpusId) <- getOrMkRootWithCorpus userMaster (Left corpusMasterName) c @@ -231,8 +259,8 @@ insertMasterDocs c lang hs = do let hs' = map addUniqId hs ids <- insertDb masterUserId masterCorpusId hs' let documentsWithId = mergeData (toInserted ids) (Map.fromList $ map viewUniqId' hs') - - let + + let fixLang (Unsupervised l n s m) = Unsupervised l n s m' where m' = case m of @@ -251,16 +279,19 @@ insertMasterDocs c lang hs = do maps <- mapNodeIdNgrams <$> documentIdWithNgrams (extractNgramsT lang') documentsWithId terms2id <- insertNgrams $ Map.keys maps let indexedNgrams = Map.mapKeys (indexNgrams terms2id) maps - + lId <- getOrMkList masterCorpusId masterUserId _ <- insertDocNgrams lId indexedNgrams + pure $ map reId ids type CorpusName = Text -getOrMkRoot :: (HasNodeError err) => Username -> Cmd err (UserId, RootId) +getOrMkRoot :: (HasNodeError err) + => Username + -> Cmd err (UserId, RootId) getOrMkRoot username = do maybeUserId <- getUser username userId <- case maybeUserId of @@ -280,8 +311,10 @@ getOrMkRoot username = do getOrMkRootWithCorpus :: (HasNodeError err, MkCorpus a) - => Username -> Either CorpusName [CorpusId] -> Maybe a - -> Cmd err (UserId, RootId, CorpusId) + => Username + -> Either CorpusName [CorpusId] + -> Maybe a + -> Cmd err (UserId, RootId, CorpusId) getOrMkRootWithCorpus username cName c = do (userId, rootId) <- getOrMkRoot username corpusId'' <- if username == userMaster @@ -301,15 +334,19 @@ getOrMkRootWithCorpus username cName c = do ------------------------------------------------------------------------ -viewUniqId' :: UniqId a => a -> (HashId, a) +viewUniqId' :: UniqId a + => a + -> (HashId, a) viewUniqId' d = maybe err (\h -> (h,d)) (view uniqId d) where err = panic "[ERROR] Database.Flow.toInsert" -toInserted :: [ReturnId] -> Map HashId ReturnId -toInserted = Map.fromList . map (\r -> (reUniqId r, r) ) - . filter (\r -> reInserted r == True) +toInserted :: [ReturnId] + -> Map HashId ReturnId +toInserted = + Map.fromList . map (\r -> (reUniqId r, r) ) + . filter (\r -> reInserted r == True) data DocumentWithId a = DocumentWithId { documentId :: !NodeId @@ -361,34 +398,36 @@ instance HasText HyperdataDocument instance ExtractNgramsT HyperdataDocument where - extractNgramsT :: TermType Lang -> HyperdataDocument -> Cmd err (Map Ngrams (Map NgramsType Int)) + extractNgramsT :: TermType Lang + -> HyperdataDocument + -> Cmd err (Map Ngrams (Map NgramsType Int)) extractNgramsT lang hd = filterNgramsT 255 <$> extractNgramsT' lang hd where - extractNgramsT' :: TermType Lang -> HyperdataDocument + extractNgramsT' :: TermType Lang + -> HyperdataDocument -> Cmd err (Map Ngrams (Map NgramsType Int)) extractNgramsT' lang' doc = do let source = text2ngrams $ maybe "Nothing" identity $ _hyperdataDocument_source doc - + institutes = map text2ngrams $ maybe ["Nothing"] (map toSchoolName . (splitOn ", ")) $ _hyperdataDocument_institutes doc - + authors = map text2ngrams $ maybe ["Nothing"] (splitOn ", ") $ _hyperdataDocument_authors doc - + terms' <- map text2ngrams <$> map (intercalate " " . _terms_label) <$> concat <$> liftIO (extractTerms lang' $ hasText doc) - + pure $ Map.fromList $ [(source, Map.singleton Sources 1)] <> [(i', Map.singleton Institutes 1) | i' <- institutes ] <> [(a', Map.singleton Authors 1) | a' <- authors ] <> [(t', Map.singleton NgramsTerms 1) | t' <- terms' ] - filterNgramsT :: Int -> Map Ngrams (Map NgramsType Int) -> Map Ngrams (Map NgramsType Int) @@ -425,13 +464,16 @@ mapNodeIdNgrams = Map.unionsWith (Map.unionWith (Map.unionWith (+))) . fmap f ------------------------------------------------------------------------ listInsert :: FlowCmdM env err m - => ListId -> Map NgramsType [NgramsElement] + => ListId + -> Map NgramsType [NgramsElement] -> m () listInsert lId ngs = mapM_ (\(typeList, ngElmts) -> putListNgrams lId typeList ngElmts ) $ toList ngs -flowList :: FlowCmdM env err m => UserId -> CorpusId +flowList :: FlowCmdM env err m + => UserId + -> CorpusId -> Map NgramsType [NgramsElement] -> m ListId flowList uId cId ngs = do diff --git a/src/Gargantext/Database/Flow/Pairing.hs b/src/Gargantext/Database/Flow/Pairing.hs index bf63f489b747bafbdc9287b759702c408041e2c7..26a7554ea83e0a15d61622c5344a5680087552c6 100644 --- a/src/Gargantext/Database/Flow/Pairing.hs +++ b/src/Gargantext/Database/Flow/Pairing.hs @@ -33,21 +33,22 @@ import Data.Text (Text, toLower) import qualified Data.Text as DT import Gargantext.Prelude hiding (sum) import Gargantext.Database.Schema.Ngrams -- (NgramsType(..)) ---import Gargantext.Database.Node.Contact -- (HyperdataContact(..)) ---import Gargantext.Database.Types.Node -- (Hyperdata(..)) -import Gargantext.Database.Node.Contact +import Gargantext.Database.Node.Contact -- (HyperdataContact(..)) import Gargantext.Database.Flow.Utils import Gargantext.Database.Utils (Cmd, runPGSQuery) -import Gargantext.Database.Types.Node (AnnuaireId, CorpusId) -import Gargantext.Database.Node.Children +import Gargantext.Database.Types.Node (AnnuaireId, CorpusId, ListId) +import Gargantext.Database.Node.Children (getContacts) import Gargantext.Core.Types (NodeType(..)) -- TODO mv this type in Types Main type Terms = Text -- | TODO : add paring policy as parameter -pairing :: AnnuaireId -> CorpusId -> Cmd err Int -pairing aId cId = do +pairing :: AnnuaireId + -> CorpusId + -> ListId + -> Cmd err Int +pairing aId cId lId = do contacts' <- getContacts aId (Just NodeContact) let contactsMap = pairingPolicyToMap toLower $ toMaps extractNgramsT contacts' @@ -56,31 +57,34 @@ pairing aId cId = do let indexedNgrams = pairMaps contactsMap ngramsMap - insertToNodeNgrams indexedNgrams - -- TODO add List + insertDocNgrams lId indexedNgrams lastName :: Terms -> Terms -lastName texte = DT.toLower $ maybe texte (\x -> if DT.length x > 3 then x else texte) (lastName' texte) +lastName texte = DT.toLower + $ maybe texte (\x -> if DT.length x > 3 then x else texte) (lastName' texte) where lastName' = lastMay . DT.splitOn " " --- TODO: this methods is dangerous (maybe equalities of the result are not taken into account --- emergency demo plan... +-- TODO: this method is dangerous (maybe equalities of the result are not taken into account +-- emergency demo plan...) pairingPolicyToMap :: (Terms -> Terms) - -> Map (NgramsT Ngrams) a -> Map (NgramsT Ngrams) a + -> Map (NgramsT Ngrams) a + -> Map (NgramsT Ngrams) a pairingPolicyToMap f = DM.mapKeys (pairingPolicy f) -pairingPolicy :: (Terms -> Terms) -> NgramsT Ngrams -> NgramsT Ngrams +pairingPolicy :: (Terms -> Terms) + -> NgramsT Ngrams + -> NgramsT Ngrams pairingPolicy f (NgramsT nt (Ngrams ng _)) = (NgramsT nt (Ngrams (f ng) 1)) -- | TODO : use Occurrences in place of Int -extractNgramsT :: HyperdataContact -> Map (NgramsT Ngrams) Int +extractNgramsT :: HyperdataContact + -> Map (NgramsT Ngrams) Int extractNgramsT contact = fromList [(NgramsT Authors a' , 1)| a' <- authors ] where authors = map text2ngrams $ catMaybes [view (hc_who . _Just . cw_lastName) contact] ---} --- NP: notice how this function is no longer specific to the ContactId type + pairMaps :: Map (NgramsT Ngrams) a -> Map (NgramsT Ngrams) NgramsId -> Map NgramsIndexed (Map NgramsType a) @@ -92,23 +96,27 @@ pairMaps m1 m2 = ] ----------------------------------------------------------------------- -getNgramsTindexed:: CorpusId -> NgramsType -> Cmd err (Map (NgramsT Ngrams) NgramsId) +getNgramsTindexed :: CorpusId + -> NgramsType + -> Cmd err (Map (NgramsT Ngrams) NgramsId) getNgramsTindexed corpusId ngramsType' = fromList <$> map (\(ngramsId',t,n) -> (NgramsT ngramsType' (Ngrams t n),ngramsId')) <$> selectNgramsTindexed corpusId ngramsType' - -selectNgramsTindexed :: CorpusId -> NgramsType -> Cmd err [(NgramsId, Terms, Int)] -selectNgramsTindexed corpusId ngramsType'' = runPGSQuery selectQuery (corpusId, ngramsTypeId ngramsType'') where - selectQuery = [sql| SELECT n.id,n.terms,n.n from ngrams n - JOIN nodes_ngrams occ ON occ.ngram_id = n.id - JOIN nodes_nodes nn ON nn.node2_id = occ.node_id - - WHERE nn.node1_id = ? - AND occ.ngrams_type = ? - AND occ.node_id = nn.node2_id - GROUP BY n.id; - |] + selectNgramsTindexed :: CorpusId + -> NgramsType + -> Cmd err [(NgramsId, Terms, Int)] + selectNgramsTindexed corpusId' ngramsType'' = runPGSQuery selectQuery (corpusId', ngramsTypeId ngramsType'') + where + selectQuery = [sql| SELECT n.id,n.terms,n.n from ngrams n + JOIN node_node_ngrams occ ON occ.ngrams_id = n.id + JOIN nodes_nodes nn ON nn.node2_id = occ.node2_id + + WHERE nn.node1_id = ? + AND occ.ngrams_type = ? + AND occ.node2_id = nn.node2_id + GROUP BY n.id; + |] {- | TODO more typed SQL queries selectNgramsTindexed :: CorpusId -> NgramsType -> Query NgramsRead @@ -124,5 +132,3 @@ selectNgramsTindexed corpusId ngramsType = proc () -> do result <- aggregate groupBy (ngrams_id ngrams) returnA -< result --} - - diff --git a/src/Gargantext/Database/Flow/Utils.hs b/src/Gargantext/Database/Flow/Utils.hs index cbab70099e406d9909b904aef785776120752174..e695d1e344b12264535f934f2e8d2364f238028b 100644 --- a/src/Gargantext/Database/Flow/Utils.hs +++ b/src/Gargantext/Database/Flow/Utils.hs @@ -22,10 +22,8 @@ import Gargantext.Prelude import Gargantext.Database.Schema.Ngrams import Gargantext.Database.Types.Node (NodeId, Node, NodePoly(..), Hyperdata) import Gargantext.Database.Utils (Cmd) -import Gargantext.Database.Schema.NodeNgram import Gargantext.Database.Schema.NodeNodeNgrams import Gargantext.Database.Types.Node -import Gargantext.Core.Types.Main (ListType(..), listTypeId) toMaps :: Hyperdata a => (a -> Map (NgramsT Ngrams) Int) -> [Node a] -> Map (NgramsT Ngrams) (Map NodeId Int) toMaps fun ns = mapNodeIdNgrams $ documentIdWithNgrams fun ns' @@ -39,8 +37,10 @@ mapNodeIdNgrams ds = DM.map (DM.fromListWith (+)) $ DM.fromListWith (<>) xs n2i = map (\d -> ((documentId . documentWithId) d, document_ngrams d)) -documentIdWithNgrams :: Hyperdata a => (a -> Map (NgramsT Ngrams) Int) - -> [DocumentWithId a] -> [DocumentIdWithNgrams a] +documentIdWithNgrams :: Hyperdata a + => (a -> Map (NgramsT Ngrams) Int) + -> [DocumentWithId a] + -> [DocumentIdWithNgrams a] documentIdWithNgrams f = map (\d -> DocumentIdWithNgrams d ((f . documentData) d)) @@ -56,19 +56,12 @@ data DocumentIdWithNgrams a = , document_ngrams :: Map (NgramsT Ngrams) Int } deriving (Show) --- | TODO for now, list Type is CandidateTerm because Graph Terms --- have to be detected in next step in the flow --- TODO remvoe this -insertToNodeNgrams :: Map NgramsIndexed (Map NgramsType (Map NodeId Int)) -> Cmd err Int -insertToNodeNgrams m = insertNodeNgrams [ NodeNgram n (_ngramsId ng) Nothing (ngramsTypeId t) (listTypeId CandidateTerm) (fromIntegral i) - | (ng, t2n2i) <- DM.toList m - , (t, n2i) <- DM.toList t2n2i - , (n, i) <- DM.toList n2i - ] - -docNgrams2nodeNodeNgrams :: CorpusId -> DocNgrams -> NodeNodeNgrams -docNgrams2nodeNodeNgrams cId (DocNgrams d n nt w) = NodeNodeNgrams Nothing cId d n nt w +docNgrams2nodeNodeNgrams :: CorpusId + -> DocNgrams + -> NodeNodeNgrams +docNgrams2nodeNodeNgrams cId (DocNgrams d n nt w) = + NodeNodeNgrams Nothing cId d n nt w data DocNgrams = DocNgrams { dn_doc_id :: DocId , dn_ngrams_id :: Int @@ -76,10 +69,14 @@ data DocNgrams = DocNgrams { dn_doc_id :: DocId , dn_weight :: Double } -insertDocNgramsOn :: CorpusId -> [DocNgrams] -> Cmd err Int +insertDocNgramsOn :: CorpusId + -> [DocNgrams] + -> Cmd err Int insertDocNgramsOn cId dn = insertNodeNodeNgrams $ (map (docNgrams2nodeNodeNgrams cId) dn) -insertDocNgrams :: CorpusId -> Map NgramsIndexed (Map NgramsType (Map NodeId Int)) -> Cmd err Int +insertDocNgrams :: CorpusId + -> Map NgramsIndexed (Map NgramsType (Map NodeId Int)) + -> Cmd err Int insertDocNgrams cId m = insertDocNgramsOn cId [ DocNgrams n (_ngramsId ng) (ngramsTypeId t) (fromIntegral i) | (ng, t2n2i) <- DM.toList m , (t, n2i) <- DM.toList t2n2i diff --git a/src/Gargantext/Database/Ngrams.hs b/src/Gargantext/Database/Ngrams.hs index 3f6a5a63b917c4268f433263d86db4e7454efb93..f93f10e0509a6d33f26785fed81cb97681b4486c 100644 --- a/src/Gargantext/Database/Ngrams.hs +++ b/src/Gargantext/Database/Ngrams.hs @@ -18,6 +18,7 @@ module Gargantext.Database.Ngrams where import Data.Text (Text) +import Control.Lens ((^.)) import Gargantext.Core.Types import Gargantext.Database.Utils (runOpaQuery, Cmd) import Gargantext.Database.Schema.Ngrams @@ -34,14 +35,14 @@ selectNgramsByDoc cIds dId nt = runOpaQuery (query cIds dId nt) join :: Query (NgramsRead, NodeNodeNgramsReadNull) join = leftJoin queryNgramsTable queryNodeNodeNgramsTable on1 where - on1 (ng,nnng) = ngrams_id ng .== nnng_ngrams_id nnng + on1 (ng,nnng) = ng^.ngrams_id .== nnng^.nnng_ngrams_id query cIds' dId' nt' = proc () -> do (ng,nnng) <- join -< () - restrict -< foldl (\b cId -> ((toNullable $ pgNodeId cId) .== nnng_node1_id nnng) .|| b) (pgBool True) cIds' - restrict -< (toNullable $ pgNodeId dId') .== nnng_node2_id nnng - restrict -< (toNullable $ pgNgramsType nt') .== nnng_ngramsType nnng - returnA -< ngrams_terms ng + restrict -< foldl (\b cId -> ((toNullable $ pgNodeId cId) .== nnng^.nnng_node1_id) .|| b) (pgBool True) cIds' + restrict -< (toNullable $ pgNodeId dId') .== nnng^.nnng_node2_id + restrict -< (toNullable $ pgNgramsType nt') .== nnng^.nnng_ngramsType + returnA -< ng^.ngrams_terms postNgrams :: CorpusId -> DocId -> [Text] -> Cmd err Int diff --git a/src/Gargantext/Database/Node/Children.hs b/src/Gargantext/Database/Node/Children.hs index 3dbcfaee1634697d46b7d86d775ce20a2a1e0a1f..75ec3dcafd4e68754dd772f9f151003fbaedea31 100644 --- a/src/Gargantext/Database/Node/Children.hs +++ b/src/Gargantext/Database/Node/Children.hs @@ -30,24 +30,34 @@ import Gargantext.Database.Schema.Node (pgNodeId) import Control.Arrow (returnA) -- | TODO: use getChildren with Proxy ? -getContacts :: ParentId -> Maybe NodeType -> Cmd err [Node HyperdataContact] +getContacts :: ParentId + -> Maybe NodeType + -> Cmd err [Node HyperdataContact] getContacts pId maybeNodeType = runOpaQuery $ selectChildren pId maybeNodeType -getChildren :: JSONB a => ParentId -> proxy a -> Maybe NodeType -> Maybe Offset -> Maybe Limit -> Cmd err [Node a] +getChildren :: JSONB a + => ParentId + -> proxy a + -> Maybe NodeType + -> Maybe Offset + -> Maybe Limit + -> Cmd err [Node a] getChildren pId _ maybeNodeType maybeOffset maybeLimit = runOpaQuery $ limit' maybeLimit $ offset' maybeOffset $ orderBy (asc _node_id) $ selectChildren pId maybeNodeType -selectChildren :: ParentId -> Maybe NodeType -> Query NodeRead +selectChildren :: ParentId + -> Maybe NodeType + -> Query NodeRead selectChildren parentId maybeNodeType = proc () -> do row@(Node nId typeName _ parent_id _ _ _) <- queryNodeTable -< () (NodeNode n1id n2id _ _) <- queryNodeNodeTable -< () - + let nodeType = maybe 0 nodeTypeId maybeNodeType restrict -< typeName .== pgInt4 nodeType - + restrict -< (.||) (parent_id .== (pgNodeId parentId)) ( (.&&) (n1id .== pgNodeId parentId) (n2id .== nId)) diff --git a/src/Gargantext/Database/Node/Document/Insert.hs b/src/Gargantext/Database/Node/Document/Insert.hs index ac01121d2ca6f6b1df638fc48880363da193f09b..f1c0d37d7a0c2798c8f159a8d76751eff2b50c63 100644 --- a/src/Gargantext/Database/Node/Document/Insert.hs +++ b/src/Gargantext/Database/Node/Document/Insert.hs @@ -186,7 +186,7 @@ queryInsert = [sql| data ReturnId = ReturnId { reInserted :: Bool -- if the document is inserted (True: is new, False: is not new) , reId :: NodeId -- always return the id of the document (even new or not new) -- this is the uniq id in the database - , reUniqId :: Text -- Hash Id with concatenation of hash parameters + , reUniqId :: Text -- Hash Id with concatenation of sha parameters } deriving (Show, Generic) instance FromRow ReturnId where @@ -204,14 +204,14 @@ instance AddUniqId HyperdataDocument addUniqId = addUniqIdsDoc where addUniqIdsDoc :: HyperdataDocument -> HyperdataDocument - addUniqIdsDoc doc = set hyperdataDocument_uniqIdBdd (Just hashBdd) - $ set hyperdataDocument_uniqId (Just hashUni) doc + addUniqIdsDoc doc = set hyperdataDocument_uniqIdBdd (Just shaBdd) + $ set hyperdataDocument_uniqId (Just shaUni) doc where - hashUni = hash $ DT.concat $ map ($ doc) hashParametersDoc - hashBdd = hash $ DT.concat $ map ($ doc) ([(\d -> maybeText (_hyperdataDocument_bdd d))] <> hashParametersDoc) + shaUni = sha $ DT.concat $ map ($ doc) shaParametersDoc + shaBdd = sha $ DT.concat $ map ($ doc) ([(\d -> maybeText (_hyperdataDocument_bdd d))] <> shaParametersDoc) - hashParametersDoc :: [(HyperdataDocument -> Text)] - hashParametersDoc = [ \d -> maybeText (_hyperdataDocument_title d) + shaParametersDoc :: [(HyperdataDocument -> Text)] + shaParametersDoc = [ \d -> maybeText (_hyperdataDocument_title d) , \d -> maybeText (_hyperdataDocument_abstract d) , \d -> maybeText (_hyperdataDocument_source d) , \d -> maybeText (_hyperdataDocument_publication_date d) @@ -226,18 +226,18 @@ instance AddUniqId HyperdataContact addUniqId = addUniqIdsContact addUniqIdsContact :: HyperdataContact -> HyperdataContact -addUniqIdsContact hc = set (hc_uniqIdBdd) (Just hashBdd) - $ set (hc_uniqId ) (Just hashUni) hc +addUniqIdsContact hc = set (hc_uniqIdBdd) (Just shaBdd) + $ set (hc_uniqId ) (Just shaUni) hc where - hashUni = uniqId $ DT.concat $ map ($ hc) hashParametersContact - hashBdd = uniqId $ DT.concat $ map ($ hc) ([\d -> maybeText (view hc_bdd d)] <> hashParametersContact) + shaUni = uniqId $ DT.concat $ map ($ hc) shaParametersContact + shaBdd = uniqId $ DT.concat $ map ($ hc) ([\d -> maybeText (view hc_bdd d)] <> shaParametersContact) uniqId :: Text -> Text uniqId = DT.pack . SHA.showDigest . SHA.sha256 . DC.pack . DT.unpack - -- | TODO add more hashparameters - hashParametersContact :: [(HyperdataContact -> Text)] - hashParametersContact = [ \d -> maybeText $ view (hc_who . _Just . cw_firstName) d + -- | TODO add more shaparameters + shaParametersContact :: [(HyperdataContact -> Text)] + shaParametersContact = [ \d -> maybeText $ view (hc_who . _Just . cw_firstName) d , \d -> maybeText $ view (hc_who . _Just . cw_lastName ) d , \d -> maybeText $ view (hc_where . _head . cw_touch . _Just . ct_mail) d ] diff --git a/src/Gargantext/Database/Schema/Ngrams.hs b/src/Gargantext/Database/Schema/Ngrams.hs index b9da31004219232cadf90e39e31e8543ac887d2a..d9f784774d161834681f27ca94ac7459193353ff 100644 --- a/src/Gargantext/Database/Schema/Ngrams.hs +++ b/src/Gargantext/Database/Schema/Ngrams.hs @@ -51,9 +51,9 @@ type NgramsId = Int type NgramsTerms = Text type Size = Int -data NgramsPoly id terms n = NgramsDb { ngrams_id :: id - , ngrams_terms :: terms - , ngrams_n :: n +data NgramsPoly id terms n = NgramsDb { _ngrams_id :: id + , _ngrams_terms :: terms + , _ngrams_n :: n } deriving (Show) type NgramsWrite = NgramsPoly (Maybe (Column PGInt4)) @@ -71,12 +71,13 @@ type NgramsReadNull = NgramsPoly (Column (Nullable PGInt4)) type NgramsDb = NgramsPoly Int Text Int $(makeAdaptorAndInstance "pNgramsDb" ''NgramsPoly) --- $(makeLensesWith abbreviatedFields ''NgramsPoly) +makeLenses ''NgramsPoly + ngramsTable :: Table NgramsWrite NgramsRead -ngramsTable = Table "ngrams" (pNgramsDb NgramsDb { ngrams_id = optional "id" - , ngrams_terms = required "terms" - , ngrams_n = required "n" +ngramsTable = Table "ngrams" (pNgramsDb NgramsDb { _ngrams_id = optional "id" + , _ngrams_terms = required "terms" + , _ngrams_n = required "n" } ) diff --git a/src/Gargantext/Database/Schema/Node.hs b/src/Gargantext/Database/Schema/Node.hs index 4c9726961a26a2c09a2c6e38401328c7590d3aa3..e755bd4daeeb923e3c8285ed4e05885dd50e0f4f 100644 --- a/src/Gargantext/Database/Schema/Node.hs +++ b/src/Gargantext/Database/Schema/Node.hs @@ -699,6 +699,7 @@ mkNode nt p u = insertNodesR [nodeDefault nt p u] mkGraph :: ParentId -> UserId -> Cmd err [GraphId] mkGraph p u = insertNodesR [nodeGraphW Nothing Nothing p u] + mkDashboard :: ParentId -> UserId -> Cmd err [NodeId] mkDashboard p u = insertNodesR [nodeDashboardW Nothing Nothing p u] where @@ -709,7 +710,6 @@ mkDashboard p u = insertNodesR [nodeDashboardW Nothing Nothing p u] dashboard = maybe arbitraryDashboard identity maybeDashboard - mkPhylo :: ParentId -> UserId -> Cmd err [NodeId] mkPhylo p u = insertNodesR [nodePhyloW Nothing Nothing p u] @@ -718,8 +718,5 @@ mkPhylo p u = insertNodesR [nodePhyloW Nothing Nothing p u] pgNodeId :: NodeId -> Column PGInt4 pgNodeId = pgInt4 . id2int - getListsWithParentId :: NodeId -> Cmd err [Node HyperdataList] getListsWithParentId n = runOpaQuery $ selectNodesWith' n (Just NodeList) - - diff --git a/src/Gargantext/Database/Schema/NodeNode.hs b/src/Gargantext/Database/Schema/NodeNode.hs index a2e9d198ed55e18430c1dcfcf564146112890efc..2504769e58665b5b15524d49df5ba9fc7d8850a7 100644 --- a/src/Gargantext/Database/Schema/NodeNode.hs +++ b/src/Gargantext/Database/Schema/NodeNode.hs @@ -25,11 +25,11 @@ commentary with @some markup@. module Gargantext.Database.Schema.NodeNode where -import Control.Lens (view) +import Control.Lens (view, (^.)) import qualified Database.PostgreSQL.Simple as PGS (Query, Only(..)) import Database.PostgreSQL.Simple.Types (Values(..), QualifiedIdentifier(..)) import Database.PostgreSQL.Simple.SqlQQ (sql) -import Control.Lens.TH (makeLensesWith, abbreviatedFields) +import Control.Lens.TH (makeLenses, makeLensesWith, abbreviatedFields) import Data.Maybe (Maybe, catMaybes) import Data.Text (Text, splitOn) import Data.Profunctor.Product.TH (makeAdaptorAndInstance) @@ -44,10 +44,10 @@ import Control.Arrow (returnA) import qualified Opaleye as O data NodeNodePoly node1_id node2_id score cat - = NodeNode { nn_node1_id :: node1_id - , nn_node2_id :: node2_id - , nn_score :: score - , nn_category :: cat + = NodeNode { _nn_node1_id :: node1_id + , _nn_node2_id :: node2_id + , _nn_score :: score + , _nn_category :: cat } deriving (Show) type NodeNodeWrite = NodeNodePoly (Column (PGInt4)) @@ -59,7 +59,7 @@ type NodeNodeRead = NodeNodePoly (Column (PGInt4)) (Column (PGInt4)) (Column (PGFloat8)) (Column (PGInt4)) - + type NodeNodeReadNull = NodeNodePoly (Column (Nullable PGInt4)) (Column (Nullable PGInt4)) (Column (Nullable PGFloat8)) @@ -68,14 +68,14 @@ type NodeNodeReadNull = NodeNodePoly (Column (Nullable PGInt4)) type NodeNode = NodeNodePoly Int Int (Maybe Double) (Maybe Int) $(makeAdaptorAndInstance "pNodeNode" ''NodeNodePoly) -$(makeLensesWith abbreviatedFields ''NodeNodePoly) +makeLenses ''NodeNodePoly nodeNodeTable :: Table NodeNodeWrite NodeNodeRead nodeNodeTable = Table "nodes_nodes" (pNodeNode - NodeNode { nn_node1_id = required "node1_id" - , nn_node2_id = required "node2_id" - , nn_score = optional "score" - , nn_category = optional "category" + NodeNode { _nn_node1_id = required "node1_id" + , _nn_node2_id = required "node2_id" + , _nn_score = optional "score" + , _nn_category = optional "category" } ) @@ -144,9 +144,9 @@ selectDocs cId = runOpaQuery (queryDocs cId) queryDocs :: CorpusId -> O.Query (Column PGJsonb) queryDocs cId = proc () -> do (n, nn) <- joinInCorpus -< () - restrict -< ( nn_node1_id nn) .== (toNullable $ pgNodeId cId) - restrict -< ( nn_category nn) .>= (toNullable $ pgInt4 1) - restrict -< (_node_typename n) .== (pgInt4 $ nodeTypeId NodeDocument) + restrict -< nn^.nn_node1_id .== (toNullable $ pgNodeId cId) + restrict -< nn^.nn_category .>= (toNullable $ pgInt4 1) + restrict -< n^.node_typename .== (pgInt4 $ nodeTypeId NodeDocument) returnA -< view (node_hyperdata) n @@ -156,9 +156,9 @@ selectDocNodes cId = runOpaQuery (queryDocNodes cId) queryDocNodes :: CorpusId -> O.Query NodeRead queryDocNodes cId = proc () -> do (n, nn) <- joinInCorpus -< () - restrict -< ( nn_node1_id nn) .== (toNullable $ pgNodeId cId) - restrict -< ( nn_category nn) .>= (toNullable $ pgInt4 1) - restrict -< (_node_typename n) .== (pgInt4 $ nodeTypeId NodeDocument) + restrict -< nn^.nn_node1_id .== (toNullable $ pgNodeId cId) + restrict -< nn^.nn_category .>= (toNullable $ pgInt4 1) + restrict -< n^.node_typename .== (pgInt4 $ nodeTypeId NodeDocument) returnA -< n @@ -166,7 +166,7 @@ joinInCorpus :: O.Query (NodeRead, NodeNodeReadNull) joinInCorpus = leftJoin queryNodeTable queryNodeNodeTable cond where cond :: (NodeRead, NodeNodeRead) -> Column PGBool - cond (n, nn) = nn_node2_id nn .== (view node_id n) + cond (n, nn) = nn^.nn_node2_id .== (view node_id n) ------------------------------------------------------------------------ diff --git a/src/Gargantext/Database/Schema/NodeNodeNgrams.hs b/src/Gargantext/Database/Schema/NodeNodeNgrams.hs index d09aca7f22a516b3c9c96307e28e19dce37f08ba..e3bc10f2b30e79c686eb06a4e36ae9c62324015d 100644 --- a/src/Gargantext/Database/Schema/NodeNodeNgrams.hs +++ b/src/Gargantext/Database/Schema/NodeNodeNgrams.hs @@ -25,7 +25,7 @@ module Gargantext.Database.Schema.NodeNodeNgrams import Prelude import Data.Maybe (Maybe) import Data.Profunctor.Product.TH (makeAdaptorAndInstance) ---import Control.Lens.TH (makeLensesWith, abbreviatedFields) +import Control.Lens.TH (makeLenses) import Gargantext.Database.Utils (Cmd, mkCmd) import Gargantext.Database.Schema.Ngrams (NgramsTypeId, pgNgramsTypeId, NgramsId) import Gargantext.Database.Schema.Node (pgNodeId) @@ -35,12 +35,12 @@ import Opaleye data NodeNodeNgramsPoly id' n1 n2 ngrams_id ngt w - = NodeNodeNgrams { nnng_id :: id' - , nnng_node1_id :: n1 - , nnng_node2_id :: n2 - , nnng_ngrams_id :: ngrams_id - , nnng_ngramsType :: ngt - , nnng_weight :: w + = NodeNodeNgrams { _nnng_id :: id' + , _nnng_node1_id :: n1 + , _nnng_node2_id :: n2 + , _nnng_ngrams_id :: ngrams_id + , _nnng_ngramsType :: ngt + , _nnng_weight :: w } deriving (Show) @@ -71,19 +71,19 @@ type NodeNodeNgramsReadNull = type NodeNodeNgrams = NodeNodeNgramsPoly (Maybe Int) CorpusId DocId NgramsId NgramsTypeId Double ---{- $(makeAdaptorAndInstance "pNodeNodeNgrams" ''NodeNodeNgramsPoly) --- $(makeLensesWith abbreviatedFields ''NodeNodeNgramsPoly) +makeLenses ''NodeNodeNgramsPoly + nodeNodeNgramsTable :: Table NodeNodeNgramsWrite NodeNodeNgramsRead nodeNodeNgramsTable = Table "node_node_ngrams" ( pNodeNodeNgrams NodeNodeNgrams - { nnng_id = optional "id" - , nnng_node1_id = required "node1_id" - , nnng_node2_id = required "node2_id" - , nnng_ngrams_id = required "ngrams_id" - , nnng_ngramsType = required "ngrams_type" - , nnng_weight = required "weight" + { _nnng_id = optional "id" + , _nnng_node1_id = required "node1_id" + , _nnng_node2_id = required "node2_id" + , _nnng_ngrams_id = required "ngrams_id" + , _nnng_ngramsType = required "ngrams_type" + , _nnng_weight = required "weight" } ) diff --git a/src/Gargantext/Database/TextSearch.hs b/src/Gargantext/Database/TextSearch.hs index e9f593062dda5358f3999b6f97f232becace6734..d2bc22e8293bd0c53c8c0c88a65d2922714f72f4 100644 --- a/src/Gargantext/Database/TextSearch.hs +++ b/src/Gargantext/Database/TextSearch.hs @@ -18,6 +18,7 @@ module Gargantext.Database.TextSearch where import Data.Aeson import Data.Map.Strict hiding (map, drop, take) import Data.Maybe +import Control.Lens ((^.)) import Data.List (intersperse, take, drop) import Data.String (IsString(..)) import Data.Text (Text, words, unpack, intercalate) @@ -43,97 +44,179 @@ import Opaleye hiding (Query, Order) ------------------------------------------------------------------------ -searchInDatabase :: ParentId -> Text -> Cmd err [(NodeId, HyperdataDocument)] +searchInDatabase :: ParentId + -> Text + -> Cmd err [(NodeId, HyperdataDocument)] searchInDatabase p t = runOpaQuery (queryInDatabase p t) - --- | Global search query where ParentId is Master Node Corpus Id -queryInDatabase :: ParentId -> Text -> O.Query (Column PGInt4, Column PGJsonb) -queryInDatabase _ q = proc () -> do - row <- queryNodeSearchTable -< () - restrict -< (_ns_search row) @@ (pgTSQuery (unpack q)) - restrict -< (_ns_typename row) .== (pgInt4 $ nodeTypeId NodeDocument) - returnA -< (_ns_id row, _ns_hyperdata row) + where + -- | Global search query where ParentId is Master Node Corpus Id + queryInDatabase :: ParentId -> Text -> O.Query (Column PGInt4, Column PGJsonb) + queryInDatabase _ q = proc () -> do + row <- queryNodeSearchTable -< () + restrict -< (_ns_search row) @@ (pgTSQuery (unpack q)) + restrict -< (_ns_typename row) .== (pgInt4 $ nodeTypeId NodeDocument) + returnA -< (_ns_id row, _ns_hyperdata row) ------------------------------------------------------------------------ -- | todo add limit and offset and order -searchInCorpus :: CorpusId -> IsTrash -> [Text] -> Maybe Offset -> Maybe Limit -> Maybe OrderBy -> Cmd err [FacetDoc] +searchInCorpus :: CorpusId + -> IsTrash + -> [Text] + -> Maybe Offset + -> Maybe Limit + -> Maybe OrderBy + -> Cmd err [FacetDoc] searchInCorpus cId t q o l order = runOpaQuery (filterWith o l order $ queryInCorpus cId t q') where q' = intercalate " | " $ map stemIt q -queryInCorpus :: CorpusId -> IsTrash -> Text -> O.Query FacetDocRead +queryInCorpus :: CorpusId + -> IsTrash + -> Text + -> O.Query FacetDocRead queryInCorpus cId t q = proc () -> do (n, nn) <- joinInCorpus -< () - restrict -< ( nn_node1_id nn) .== (toNullable $ pgNodeId cId) + restrict -< ( nn^.nn_node1_id) .== (toNullable $ pgNodeId cId) restrict -< if t - then ( nn_category nn) .== (toNullable $ pgInt4 0) - else ( nn_category nn) .>= (toNullable $ pgInt4 1) - restrict -< (_ns_search n) @@ (pgTSQuery (unpack q)) - restrict -< (_ns_typename n) .== (pgInt4 $ nodeTypeId NodeDocument) - returnA -< FacetDoc (_ns_id n) (_ns_date n) (_ns_name n) (_ns_hyperdata n) (nn_category nn) (nn_score nn) + then ( nn^.nn_category) .== (toNullable $ pgInt4 0) + else ( nn^.nn_category) .>= (toNullable $ pgInt4 1) + restrict -< (n ^. ns_search) @@ (pgTSQuery (unpack q)) + restrict -< (n ^. ns_typename) .== (pgInt4 $ nodeTypeId NodeDocument) + returnA -< FacetDoc (n^.ns_id ) + (n^.ns_date ) + (n^.ns_name ) + (n^.ns_hyperdata) + (nn^.nn_category) + (nn^.nn_score ) joinInCorpus :: O.Query (NodeSearchRead, NodeNodeReadNull) joinInCorpus = leftJoin queryNodeSearchTable queryNodeNodeTable cond where cond :: (NodeSearchRead, NodeNodeRead) -> Column PGBool - cond (n, nn) = nn_node2_id nn .== _ns_id n + cond (n, nn) = nn^.nn_node2_id .== _ns_id n ------------------------------------------------------------------------ type AuthorName = Text -- | TODO Optim: Offset and Limit in the Query -- TODO-SECURITY check -searchInCorpusWithContacts :: CorpusId -> [Text] -> Maybe Offset -> Maybe Limit -> Maybe OrderBy -> Cmd err [FacetPaired Int UTCTime HyperdataDocument Int [Pair Int Text]] -searchInCorpusWithContacts cId q o l order = take (maybe 5 identity l) <$> drop (maybe 0 identity o) - <$> map (\((i,u,h,s), ps) -> FacetPaired i u h s (catMaybes ps)) +searchInCorpusWithContacts + :: CorpusId + -> ListId + -> [Text] + -> Maybe Offset + -> Maybe Limit + -> Maybe OrderBy + -> Cmd err [FacetPaired Int UTCTime HyperdataDocument Int [Pair Int Text]] +searchInCorpusWithContacts cId lId q o l order = + take (maybe 10 identity l) + <$> drop (maybe 0 identity o) + <$> map (\((i,u,h,s), ps) -> FacetPaired i u h s ps) <$> toList <$> fromListWith (<>) - <$> map (\(FacetPaired i u h s p) -> ((i,u,h,s), [maybePair p])) - <$> searchInCorpusWithContacts' cId q o l order - where - maybePair (Pair Nothing Nothing) = Nothing - maybePair (Pair _ Nothing) = Nothing - maybePair (Pair Nothing _) = Nothing - maybePair (Pair (Just p_id) (Just p_label)) = Just $ Pair p_id p_label + <$> map (\(FacetPaired i u h s (p1,p2)) -> ( (i,u,h,s) + , catMaybes [Pair <$> p1 <*> p2] + ) + ) + <$> searchInCorpusWithContacts' cId lId q o l order -- TODO-SECURITY check -searchInCorpusWithContacts' :: CorpusId -> [Text] -> Maybe Offset -> Maybe Limit -> Maybe OrderBy -> Cmd err [(FacetPaired Int UTCTime HyperdataDocument Int (Pair (Maybe Int) (Maybe Text)))] -searchInCorpusWithContacts' cId q o l order = runOpaQuery $ queryInCorpusWithContacts cId q' o l order - where - q' = intercalate " | " $ map stemIt q - +searchInCorpusWithContacts' + :: CorpusId + -> ListId + -> [Text] + -> Maybe Offset + -> Maybe Limit + -> Maybe OrderBy + -> Cmd err [(FacetPaired Int UTCTime HyperdataDocument Int (Maybe Int, Maybe Text))] +searchInCorpusWithContacts' cId lId q o l order = + runOpaQuery $ queryInCorpusWithContacts cId lId q' o l order + where + q' = intercalate " | " $ map stemIt q -queryInCorpusWithContacts :: CorpusId -> Text -> Maybe Offset -> Maybe Limit -> Maybe OrderBy -> O.Query FacetPairedRead -queryInCorpusWithContacts cId q _ _ _ = proc () -> do - (docs, (corpusDoc, (_docNgrams, (ngrams', (_, contacts))))) <- joinInCorpusWithContacts -< () - restrict -< (_ns_search docs) @@ (pgTSQuery $ unpack q ) - restrict -< (_ns_typename docs) .== (pgInt4 $ nodeTypeId NodeDocument) - restrict -< (nn_node1_id corpusDoc) .== (toNullable $ pgNodeId cId) +queryInCorpusWithContacts + :: CorpusId + -> ListId + -> Text + -> Maybe Offset + -> Maybe Limit + -> Maybe OrderBy + -> O.Query FacetPairedRead +queryInCorpusWithContacts cId lId q _ _ _ = proc () -> do + (docs, (corpusDoc, (docNgrams, (ngrams', (_, contacts))))) <- joinInCorpusWithContacts -< () + restrict -< (docs^.ns_search) @@ (pgTSQuery $ unpack q ) + restrict -< (docs^.ns_typename) .== (pgInt4 $ nodeTypeId NodeDocument) + restrict -< (docNgrams^.nnng_node2_id) .== (toNullable $ pgNodeId lId) + restrict -< (corpusDoc^.nn_node1_id) .== (toNullable $ pgNodeId cId) -- restrict -< (nng_listType docNgrams) .== (toNullable $ pgNgramsType Authors) - restrict -< (_node_typename contacts) .== (toNullable $ pgInt4 $ nodeTypeId NodeContact) + restrict -< (contacts^.node_typename) .== (toNullable $ pgInt4 $ nodeTypeId NodeContact) -- let contact_id = ifThenElse (isNull $ _node_id contacts) (toNullable $ pgInt4 0) (_node_id contacts) - returnA -< FacetPaired (_ns_id docs) (_ns_date docs) (_ns_hyperdata docs) (pgInt4 0) (Pair (_node_id contacts) (ngrams_terms ngrams')) + returnA -< FacetPaired (docs^.ns_id) (docs^.ns_date) (docs^.ns_hyperdata) (pgInt4 0) (contacts^.node_id, ngrams'^.ngrams_terms) -joinInCorpusWithContacts :: O.Query (NodeSearchRead, (NodeNodeReadNull, (NodeNodeNgramsReadNull, (NgramsReadNull, (NodeNodeNgramsReadNull, NodeReadNull))))) -joinInCorpusWithContacts = leftJoin6 queryNodeTable queryNodeNodeNgramsTable queryNgramsTable queryNodeNodeNgramsTable queryNodeNodeTable queryNodeSearchTable cond12 cond23 cond34 cond45 cond56 +joinInCorpusWithContacts :: O.Query ( NodeSearchRead + , ( NodeNodeReadNull + , ( NodeNodeNgramsReadNull + , ( NgramsReadNull + , ( NodeNodeNgramsReadNull + , NodeReadNull + ) + ) + ) + ) + ) +joinInCorpusWithContacts = + leftJoin6 + queryNodeTable + queryNodeNodeNgramsTable + queryNgramsTable + queryNodeNodeNgramsTable + queryNodeNodeTable + queryNodeSearchTable + cond12 + cond23 + cond34 + cond45 + cond56 where - cond12 :: (NodeNodeNgramsRead, NodeRead) -> Column PGBool - cond12 (ng3, n2) = _node_id n2 .== nnng_node1_id ng3 ---------- - cond23 :: (NgramsRead, (NodeNodeNgramsRead, NodeReadNull)) -> Column PGBool - cond23 (ng2, (nnng2, _)) = nnng_ngrams_id nnng2 .== ngrams_id ng2 - - cond34 :: (NodeNodeNgramsRead, (NgramsRead, (NodeNodeNgramsReadNull, NodeReadNull))) -> Column PGBool - cond34 (nng, (ng, (_,_))) = ngrams_id ng .== nnng_ngrams_id nng - - cond45 :: (NodeNodeRead, (NodeNodeNgramsRead, (NgramsReadNull, (NodeNodeNgramsReadNull, NodeReadNull)))) -> Column PGBool - cond45 (nn, (nng, (_,(_,_)))) = nnng_node1_id nng .== nn_node2_id nn - - cond56 :: (NodeSearchRead, (NodeNodeRead, (NodeNodeNgramsReadNull, (NgramsReadNull, (NodeNodeNgramsReadNull, NodeReadNull))))) -> Column PGBool - cond56 (n, (nn, (_,(_,(_,_))))) = _ns_id n .== nn_node2_id nn - + cond12 :: (NodeNodeNgramsRead, NodeRead) -> Column PGBool + cond12 (ng3, n2) = n2^.node_id .== ng3^.nnng_node1_id + cond23 :: (NgramsRead, (NodeNodeNgramsRead, NodeReadNull)) -> Column PGBool + cond23 (ng2, (nnng2, _)) = nnng2^.nnng_ngrams_id .== ng2^.ngrams_id + cond34 :: ( NodeNodeNgramsRead + , ( NgramsRead + , ( NodeNodeNgramsReadNull + , NodeReadNull + ) + ) + ) -> Column PGBool + cond34 (nng, (ng, (_,_))) = ng^.ngrams_id .== nng^.nnng_ngrams_id + + cond45 :: ( NodeNodeRead + , ( NodeNodeNgramsRead + , ( NgramsReadNull + , ( NodeNodeNgramsReadNull + , NodeReadNull + ) + ) + ) + ) -> Column PGBool + cond45 (nn, (nng, (_,(_,_)))) = nng^.nnng_node1_id .== nn^.nn_node2_id + + cond56 :: ( NodeSearchRead + , ( NodeNodeRead + , ( NodeNodeNgramsReadNull + , ( NgramsReadNull + , ( NodeNodeNgramsReadNull + , NodeReadNull + ) + ) + ) + ) + ) -> Column PGBool + cond56 (n, (nn, (_,(_,(_,_))))) = _ns_id n .== nn^.nn_node2_id + newtype TSQuery = UnsafeTSQuery [Text] diff --git a/src/Gargantext/Database/Types/Node.hs b/src/Gargantext/Database/Types/Node.hs index 482a18624c1b9798fa0497feeb8569443ed915be..fc97b0af113f909b259dc21d8fb5756b34f98629 100644 --- a/src/Gargantext/Database/Types/Node.hs +++ b/src/Gargantext/Database/Types/Node.hs @@ -479,7 +479,7 @@ data NodePolySearch id typename userId hyperdata search = NodeSearch { _ns_id :: id , _ns_typename :: typename , _ns_userId :: userId - -- , nodeUniqId :: hashId + -- , nodeUniqId :: shaId , _ns_parentId :: parentId , _ns_name :: name , _ns_date :: date diff --git a/src/Gargantext/Prelude/Utils.hs b/src/Gargantext/Prelude/Utils.hs index e21b8eabe5d3d4c82a66232b3b3f140518cf06cf..c5e96b9cc0fd14154aab40f0bbbece44e7b9421d 100644 --- a/src/Gargantext/Prelude/Utils.hs +++ b/src/Gargantext/Prelude/Utils.hs @@ -85,7 +85,7 @@ writeFile :: (MonadReader env m, MonadIO m, HasSettings env, SaveFile a) => a -> m FilePath writeFile a = do dataPath <- view (settings . fileFolder) <$> ask - (fp,fn) <- liftIO $ (toPath 3) . hash . Text.pack . show <$> newStdGen + (fp,fn) <- liftIO $ (toPath 3) . sha . Text.pack . show <$> newStdGen let foldPath = dataPath <> "/" <> fp filePath = foldPath <> "/" <> fn