2015-10-16 13:32:47 +00:00
|
|
|
module Handler.Search where
|
|
|
|
|
|
|
|
import Import
|
2015-10-17 23:28:25 +00:00
|
|
|
import Handler.Commons
|
2015-10-16 19:57:18 +00:00
|
|
|
import Data.Time.Clock
|
2015-10-16 13:32:47 +00:00
|
|
|
import Data.Aeson
|
2015-10-16 19:57:18 +00:00
|
|
|
import Data.Maybe
|
|
|
|
import qualified Data.Text as T
|
2015-10-16 13:32:47 +00:00
|
|
|
import Database.Bloodhound
|
2015-10-17 01:09:04 +00:00
|
|
|
import Network.HTTP.Client (responseBody)
|
2015-10-17 18:03:29 +00:00
|
|
|
import System.FilePath.Posix
|
2015-10-16 13:32:47 +00:00
|
|
|
|
|
|
|
getSearchR :: Handler Html
|
|
|
|
getSearchR = do
|
|
|
|
((res, widget), _) <- runFormGet searchForm
|
2015-10-17 19:52:01 +00:00
|
|
|
case res of
|
|
|
|
FormSuccess query -> do
|
|
|
|
(ru, ra, rm, rc) <- getResults query
|
|
|
|
a <- return $ (decode (responseBody ru) :: Maybe (SearchResult SearchUser))
|
|
|
|
b <- return $ (decode (responseBody ra) :: Maybe (SearchResult SearchAlbum))
|
|
|
|
c <- return $ (decode (responseBody rm) :: Maybe (SearchResult SearchMedium))
|
|
|
|
d <- return $ (decode (responseBody rc) :: Maybe (SearchResult SearchComment))
|
2015-10-16 19:57:18 +00:00
|
|
|
hitListA <- case a of
|
|
|
|
Just as -> return $ hits $ searchHits as
|
|
|
|
Nothing -> return []
|
|
|
|
hitListB <- case b of
|
|
|
|
Just bs -> return $ hits $ searchHits bs
|
|
|
|
Nothing -> return []
|
|
|
|
hitListC <- case c of
|
|
|
|
Just cs -> return $ hits $ searchHits cs
|
|
|
|
Nothing -> return []
|
|
|
|
hitListD <- case d of
|
|
|
|
Just ds -> return $ hits $ searchHits ds
|
|
|
|
Nothing -> return []
|
|
|
|
userIdList <- return $ catMaybes $ map (\h -> do
|
|
|
|
if
|
|
|
|
hitIndex h == IndexName "user"
|
|
|
|
then do
|
|
|
|
DocId theId <- return $ hitDocId h
|
|
|
|
Just $ (packKey theId :: UserId)
|
|
|
|
else
|
|
|
|
Nothing
|
|
|
|
) hitListA
|
|
|
|
albumIdList <- return $ catMaybes $ map (\h -> do
|
|
|
|
if
|
|
|
|
hitIndex h == IndexName "album"
|
|
|
|
then do
|
|
|
|
DocId theId <- return $ hitDocId h
|
|
|
|
Just $ (packKey theId :: AlbumId)
|
|
|
|
else
|
|
|
|
Nothing
|
|
|
|
) hitListB
|
|
|
|
mediumIdList <- return $ catMaybes $ map (\h -> do
|
|
|
|
if
|
|
|
|
hitIndex h == IndexName "medium"
|
|
|
|
then do
|
|
|
|
DocId theId <- return $ hitDocId h
|
|
|
|
Just $ (packKey theId :: MediumId)
|
|
|
|
else
|
|
|
|
Nothing
|
|
|
|
) hitListC
|
|
|
|
commentIdList <- return $ catMaybes $ map (\h -> do
|
|
|
|
if
|
|
|
|
hitIndex h == IndexName "comment"
|
|
|
|
then do
|
|
|
|
DocId theId <- return $ hitDocId h
|
|
|
|
Just $ (packKey theId :: CommentId)
|
|
|
|
else
|
|
|
|
Nothing
|
|
|
|
) hitListD
|
2015-10-17 01:09:04 +00:00
|
|
|
userList <- return . catMaybes =<< mapM (\i -> runDB $ selectFirst [UserId ==. i] []) userIdList
|
|
|
|
albumList <- return . catMaybes =<< mapM (\i -> runDB $ selectFirst [AlbumId ==. i] []) albumIdList
|
|
|
|
mediumList <- return . catMaybes =<< mapM (\i -> runDB $ selectFirst [MediumId ==. i] []) mediumIdList
|
|
|
|
commentList <- return . catMaybes =<< mapM (\i -> runDB $ selectFirst [CommentId ==. i] []) commentIdList
|
|
|
|
let allEmpty = (null userList) && (null albumList) && (null mediumList) && (null commentList)
|
2015-10-17 19:52:01 +00:00
|
|
|
defaultLayout $ do
|
|
|
|
setTitle $ toHtml $ "Eidolon :: Search results for " ++ (T.unpack query)
|
2015-10-17 01:09:04 +00:00
|
|
|
$(widgetFile "result")
|
2015-10-17 19:52:01 +00:00
|
|
|
_ ->
|
|
|
|
defaultLayout $ do
|
|
|
|
setTitle "Eidolon :: Search"
|
2015-10-16 19:57:18 +00:00
|
|
|
$(widgetFile "search")
|
2015-10-16 13:32:47 +00:00
|
|
|
|
2015-10-16 19:57:18 +00:00
|
|
|
searchForm :: Form T.Text
|
2015-10-16 13:32:47 +00:00
|
|
|
searchForm = renderDivs $ areq (searchField True) "Search" Nothing
|
|
|
|
|
2015-10-17 18:03:29 +00:00
|
|
|
getResults :: Text -> Handler (Reply, Reply, Reply, Reply)
|
2015-10-16 13:32:47 +00:00
|
|
|
getResults query = do
|
2015-10-18 00:51:51 +00:00
|
|
|
esQuery <- return $ QueryFuzzyLikeThisQuery $ FuzzyLikeThisQuery
|
|
|
|
{ fuzzyLikeFields = [FieldName "_all"]
|
|
|
|
, fuzzyLikeText = query
|
|
|
|
, fuzzyLikeMaxQueryTerms = MaxQueryTerms 25
|
|
|
|
, fuzzyLikeIgnoreTermFrequency = IgnoreTermFrequency False
|
|
|
|
, fuzzyLikeFuzziness = Fuzziness 0.6
|
|
|
|
, fuzzyLikePrefixLength = PrefixLength 0
|
|
|
|
, fuzzyLikeBoost = Boost 1.0
|
|
|
|
, fuzzyLikeAnalyzer = Nothing
|
|
|
|
}
|
2015-10-17 23:28:25 +00:00
|
|
|
su <- runBH' $ searchByIndex (IndexName "user") $ mkSearch (Just esQuery) Nothing
|
|
|
|
sa <- runBH' $ searchByIndex (IndexName "album") $ mkSearch (Just esQuery) Nothing
|
|
|
|
sm <- runBH' $ searchByIndex (IndexName "medium") $ mkSearch (Just esQuery) Nothing
|
|
|
|
sc <- runBH' $ searchByIndex (IndexName "comment") $ mkSearch (Just esQuery) Nothing
|
2015-10-17 18:03:29 +00:00
|
|
|
return (su, sa, sm, sc)
|
2015-10-16 19:57:18 +00:00
|
|
|
|
|
|
|
data SearchUser = SearchUser
|
|
|
|
{ suName :: T.Text
|
|
|
|
, suSlug :: T.Text
|
|
|
|
}
|
|
|
|
|
|
|
|
instance FromJSON SearchUser where
|
|
|
|
parseJSON (Object o) = SearchUser
|
|
|
|
<$> o .: "name"
|
|
|
|
<*> o .: "slug"
|
|
|
|
parseJSON _ = mempty
|
|
|
|
|
|
|
|
data SearchAlbum = SearchAlbum
|
|
|
|
{ saName :: T.Text }
|
|
|
|
|
|
|
|
instance FromJSON SearchAlbum where
|
|
|
|
parseJSON (Object o) = SearchAlbum <$> o .: "name"
|
|
|
|
parseJSON _ = mempty
|
|
|
|
|
|
|
|
data SearchMedium = SearchMedium
|
|
|
|
{ smName :: Text
|
|
|
|
, smTime :: UTCTime
|
|
|
|
, smDescription :: Textarea
|
|
|
|
, smTags :: [T.Text]
|
|
|
|
}
|
|
|
|
|
|
|
|
instance FromJSON SearchMedium where
|
|
|
|
parseJSON (Object o) = SearchMedium
|
|
|
|
<$> o .: "name"
|
|
|
|
<*> o .: "time"
|
|
|
|
<*> o .: "description"
|
|
|
|
<*> o .: "tags"
|
|
|
|
parseJSON _ = mempty
|
|
|
|
|
|
|
|
data SearchComment = SearchComment
|
|
|
|
{ scAuthor :: Text
|
|
|
|
, scTime :: UTCTime
|
|
|
|
, scContent :: Text
|
|
|
|
}
|
|
|
|
|
|
|
|
instance FromJSON SearchComment where
|
|
|
|
parseJSON (Object o) = SearchComment
|
|
|
|
<$> o .: "author"
|
|
|
|
<*> o .: "time"
|
|
|
|
<*> o .: "content"
|
|
|
|
parseJSON _ = mempty
|