{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} module Database.Bloodhound.Internal.Highlight where import Bloodhound.Import import qualified Data.Map.Strict as M import Database.Bloodhound.Internal.Newtypes import Database.Bloodhound.Internal.Query type HitHighlight = M.Map Text [Text] data Highlights = Highlights { globalsettings :: Maybe HighlightSettings , highlightFields :: [FieldHighlight] } deriving (Eq, Show) instance ToJSON Highlights where toJSON (Highlights global fields) = omitNulls (("fields" .= fields) : highlightSettingsPairs global) data FieldHighlight = FieldHighlight FieldName (Maybe HighlightSettings) deriving (Eq, Show) instance ToJSON FieldHighlight where toJSON (FieldHighlight (FieldName fName) (Just fSettings)) = object [ fromText fName .= fSettings ] toJSON (FieldHighlight (FieldName fName) Nothing) = object [ fromText fName .= emptyObject ] data HighlightSettings = Plain PlainHighlight | Postings PostingsHighlight | FastVector FastVectorHighlight deriving (Eq, Show) instance ToJSON HighlightSettings where toJSON hs = omitNulls (highlightSettingsPairs (Just hs)) data PlainHighlight = PlainHighlight { plainCommon :: Maybe CommonHighlight , plainNonPost :: Maybe NonPostings } deriving (Eq, Show) -- This requires that index_options are set to 'offset' in the mapping. data PostingsHighlight = PostingsHighlight (Maybe CommonHighlight) deriving (Eq, Show) -- This requires that term_vector is set to 'with_positions_offsets' in the mapping. data FastVectorHighlight = FastVectorHighlight { fvCommon :: Maybe CommonHighlight , fvNonPostSettings :: Maybe NonPostings , boundaryChars :: Maybe Text , boundaryMaxScan :: Maybe Int , fragmentOffset :: Maybe Int , matchedFields :: [Text] , phraseLimit :: Maybe Int } deriving (Eq, Show) data CommonHighlight = CommonHighlight { order :: Maybe Text , forceSource :: Maybe Bool , tag :: Maybe HighlightTag , encoder :: Maybe HighlightEncoder , noMatchSize :: Maybe Int , highlightQuery :: Maybe Query , requireFieldMatch :: Maybe Bool } deriving (Eq, Show) -- Settings that are only applicable to FastVector and Plain highlighters. data NonPostings = NonPostings { fragmentSize :: Maybe Int , numberOfFragments :: Maybe Int } deriving (Eq, Show) data HighlightEncoder = DefaultEncoder | HTMLEncoder deriving (Eq, Show) instance ToJSON HighlightEncoder where toJSON DefaultEncoder = String "default" toJSON HTMLEncoder = String "html" -- NOTE: Should the tags use some kind of HTML type, rather than Text? data HighlightTag = TagSchema Text -- Only uses more than the first value in the lists if fvh | CustomTags ([Text], [Text]) deriving (Eq, Show) highlightSettingsPairs :: Maybe HighlightSettings -> [Pair] highlightSettingsPairs Nothing = [] highlightSettingsPairs (Just (Plain plh)) = plainHighPairs (Just plh) highlightSettingsPairs (Just (Postings ph)) = postHighPairs (Just ph) highlightSettingsPairs (Just (FastVector fvh)) = fastVectorHighPairs (Just fvh) plainHighPairs :: Maybe PlainHighlight -> [Pair] plainHighPairs Nothing = [] plainHighPairs (Just (PlainHighlight plCom plNonPost)) = [ "type" .= String "plain"] ++ commonHighlightPairs plCom ++ nonPostingsToPairs plNonPost postHighPairs :: Maybe PostingsHighlight -> [Pair] postHighPairs Nothing = [] postHighPairs (Just (PostingsHighlight pCom)) = ("type" .= String "postings") : commonHighlightPairs pCom fastVectorHighPairs :: Maybe FastVectorHighlight -> [Pair] fastVectorHighPairs Nothing = [] fastVectorHighPairs (Just (FastVectorHighlight fvCom fvNonPostSettings' fvBoundChars fvBoundMaxScan fvFragOff fvMatchedFields fvPhraseLim)) = [ "type" .= String "fvh" , "boundary_chars" .= fvBoundChars , "boundary_max_scan" .= fvBoundMaxScan , "fragment_offset" .= fvFragOff , "matched_fields" .= fvMatchedFields , "phraseLimit" .= fvPhraseLim] ++ commonHighlightPairs fvCom ++ nonPostingsToPairs fvNonPostSettings' commonHighlightPairs :: Maybe CommonHighlight -> [Pair] commonHighlightPairs Nothing = [] commonHighlightPairs (Just (CommonHighlight chScore chForceSource chTag chEncoder chNoMatchSize chHighlightQuery chRequireFieldMatch)) = [ "order" .= chScore , "force_source" .= chForceSource , "encoder" .= chEncoder , "no_match_size" .= chNoMatchSize , "highlight_query" .= chHighlightQuery , "require_fieldMatch" .= chRequireFieldMatch ] ++ highlightTagToPairs chTag nonPostingsToPairs :: Maybe NonPostings -> [Pair] nonPostingsToPairs Nothing = [] nonPostingsToPairs (Just (NonPostings npFragSize npNumOfFrags)) = [ "fragment_size" .= npFragSize , "number_of_fragments" .= npNumOfFrags ] highlightTagToPairs :: Maybe HighlightTag -> [Pair] highlightTagToPairs (Just (TagSchema _)) = [ "scheme" .= String "default" ] highlightTagToPairs (Just (CustomTags (pre, post))) = [ "pre_tags" .= pre , "post_tags" .= post ] highlightTagToPairs Nothing = []