@@ -162,20 +162,33 @@ module Database.Bloodhound.Types
162 , BucketAggregation(..)
162 , BucketAggregation(..)
163 , TermsAggregation(..)
163 , TermsAggregation(..)
164 , DateHistogramAggregation(..)
164 , DateHistogramAggregation(..)
167+ , FieldHighlight(..)
168+ , HighlightSettings(..)
169+ , PlainHighlight(..)
170+ , PostingsHighlight(..)
171+ , FastVectorHighlight(..)
172+ , CommonHighlight(..)
174+ , HighlightEncoder(..)
165 , TermsResult(..)
178 , TermsResult(..)
166 , DateHistogramResult(..)
179 , DateHistogramResult(..)
169import Control.Applicative
182import Control.Applicative
170import Data.Aeson
183import Data.Aeson
171−import Data.Aeson.Types (parseMaybe)
184+import Data.Aeson.Types (Pair, emptyObject, parseMaybe)
172import qualified Data.ByteString.Lazy.Char8 as L
185import qualified Data.ByteString.Lazy.Char8 as L
173import Data.List (nub)
186import Data.List (nub)
174import Data.List.NonEmpty (NonEmpty (..))
187import Data.List.NonEmpty (NonEmpty (..))
188+import qualified Data.Map.Strict as M
175import Data.Monoid
189import Data.Monoid
176import Data.Text (Text)
190import Data.Text (Text)
177import qualified Data.Text as T
191import qualified Data.Text as T
178−import qualified Data.Map.Strict as M
179import Data.Time.Clock (UTCTime)
192import Data.Time.Clock (UTCTime)
180import qualified Data.Vector as V
193import qualified Data.Vector as V
181import GHC.Generics (Generic)
194import GHC.Generics (Generic)
@@ -496,15 +509,71 @@ type TrackSortScores = Bool
496type From = Int
509type From = Int
497type Size = Int
510type Size = Int
499−data Search = Search { queryBody :: Maybe Query
512+data Search = Search { queryBody :: Maybe Query
500− , filterBody :: Maybe Filter
513+ , filterBody :: Maybe Filter
501− , sortBody :: Maybe Sort
514+ , sortBody :: Maybe Sort
502− , aggBody :: Maybe Aggregations
515+ , aggBody :: Maybe Aggregations
516+ , highlight :: Maybe Highlights
503 -- default False
517 -- default False
504 , trackSortScores :: TrackSortScores
518 , trackSortScores :: TrackSortScores
505 , from :: From
519 , from :: From
506 , size :: Size } deriving (Eq, Show)
520 , size :: Size } deriving (Eq, Show)
522+data Highlights = Highlights { globalsettings :: Maybe HighlightSettings
523+ , highlightFields :: [FieldHighlight]
524+ } deriving (Show, Eq)
526+data FieldHighlight = FieldHighlight FieldName (Maybe HighlightSettings)
530+data HighlightSettings = Plain PlainHighlight
531+ | Postings PostingsHighlight
532+ | FastVector FastVectorHighlight
534+data PlainHighlight =
535+ PlainHighlight { plainCommon :: Maybe CommonHighlight
536+ , plainNonPost :: Maybe NonPostings } deriving (Show, Eq)
538+ -- This requires that index_options are set to 'offset' in the mapping.
539+data PostingsHighlight = PostingsHighlight (Maybe CommonHighlight) deriving (Show, Eq)
541+-- This requires that term_vector is set to 'with_positions_offsets' in the mapping.
542+data FastVectorHighlight =
543+ FastVectorHighlight { fvCommon :: Maybe CommonHighlight
544+ , fvNonPostSettings :: Maybe NonPostings
545+ , boundaryChars :: Maybe Text
546+ , boundaryMaxScan :: Maybe Int
547+ , fragmentOffset :: Maybe Int
548+ , matchedFields :: [Text]
549+ , phraseLimit :: Maybe Int
550+ } deriving (Show, Eq)
552+data CommonHighlight =
553+ CommonHighlight { order :: Maybe Text
554+ , forceSource :: Maybe Bool
555+ , tag :: Maybe HighlightTag
556+ , encoder :: Maybe HighlightEncoder
557+ , noMatchSize :: Maybe Int
558+ , highlightQuery :: Maybe Query
559+ , requireFieldMatch :: Maybe Bool
560+ } deriving (Show, Eq)
562+-- Settings that are only applicable to FastVector and Plain highlighters.
564+ NonPostings { fragmentSize :: Maybe Int
565+ , numberOfFragments :: Maybe Int} deriving (Show, Eq)
567+data HighlightEncoder = DefaultEncoder
571+-- NOTE: Should the tags use some kind of HTML type, rather than Text?
572+data HighlightTag = TagSchema Text
573+ | CustomTags ([Text], [Text]) -- Only uses more than the first value in the lists if fvh
508data Query =
577data Query =
509 TermQuery Term (Maybe Boost)
578 TermQuery Term (Maybe Boost)
510 | TermsQuery [Term] MinimumMatch
579 | TermsQuery [Term] MinimumMatch
@@ -938,7 +1007,7 @@ data DistanceRange =
938 DistanceRange { distanceFrom :: Distance
1007 DistanceRange { distanceFrom :: Distance
939 , distanceTo :: Distance } deriving (Eq, Show)
1008 , distanceTo :: Distance } deriving (Eq, Show)
941−data FromJSON a => SearchResult a =
1010+data (FromJSON a) => SearchResult a =
942 SearchResult { took :: Int
1011 SearchResult { took :: Int
943 , timedOut :: Bool
1012 , timedOut :: Bool
944 , shards :: ShardResult
1013 , shards :: ShardResult
@@ -947,23 +1016,26 @@ data FromJSON a => SearchResult a =
948type Score = Double
1017type Score = Double
950−data FromJSON a => SearchHits a =
1019+data (FromJSON a) => SearchHits a =
951 SearchHits { hitsTotal :: Int
1020 SearchHits { hitsTotal :: Int
952 , maxScore :: Score
1021 , maxScore :: Score
953 , hits :: [Hit a] } deriving (Eq, Show)
1022 , hits :: [Hit a] } deriving (Eq, Show)
955−data FromJSON a => Hit a =
1024+data (FromJSON a) => Hit a =
956− Hit { hitIndex :: IndexName
1025+ Hit { hitIndex :: IndexName
957− , hitType :: MappingName
1026+ , hitType :: MappingName
958− , hitDocId :: DocId
1027+ , hitDocId :: DocId
959− , hitScore :: Score
1028+ , hitScore :: Score
960− , hitSource :: a } deriving (Eq, Show)
1029+ , hitSource :: a
1030+ , hitHighlight :: Maybe HitHighlight } deriving (Eq, Show)
962data ShardResult =
1032data ShardResult =
963 ShardResult { shardTotal :: Int
1033 ShardResult { shardTotal :: Int
964 , shardsSuccessful :: Int
1034 , shardsSuccessful :: Int
965 , shardsFailed :: Int } deriving (Eq, Show, Generic)
1035 , shardsFailed :: Int } deriving (Eq, Show, Generic)
1037+type HitHighlight = M.Map Text [Text]
967showText :: Show a => a -> Text
1039showText :: Show a => a -> Text
968showText = T.pack . show
1040showText = T.pack . show
@@ -1003,7 +1075,7 @@ data Interval = Year
1005 | Minute
1077 | Minute
1006− | Second
1078+ | Second
1007 | FractionalInterval Float TimeInterval deriving (Eq, Show)
1079 | FractionalInterval Float TimeInterval deriving (Eq, Show)
1009data Aggregation = TermsAgg TermsAggregation
1081data Aggregation = TermsAgg TermsAggregation
@@ -1022,14 +1094,14 @@ data TermsAggregation = TermsAggregation { term :: Either Text Text
1022 , termAggs :: Maybe Aggregations
1094 , termAggs :: Maybe Aggregations
1023 } deriving (Eq, Show)
1095 } deriving (Eq, Show)
1025−data DateHistogramAggregation = DateHistogramAggregation { dateField :: FieldName
1097+data DateHistogramAggregation = DateHistogramAggregation { dateField :: FieldName
1026− , dateInterval :: Interval
1098+ , dateInterval :: Interval
1027− , dateFormat :: Maybe Text
1099+ , dateFormat :: Maybe Text
1028− , datePreZone :: Maybe Text
1100+ , datePreZone :: Maybe Text
1029− , datePostZone :: Maybe Text
1101+ , datePostZone :: Maybe Text
1030− , datePreOffset :: Maybe Text
1102+ , datePreOffset :: Maybe Text
1031− , datePostOffset :: Maybe Text
1103+ , datePostOffset :: Maybe Text
1032− , dateAggs :: Maybe Aggregations
1104+ , dateAggs :: Maybe Aggregations
1033 } deriving (Eq, Show)
1105 } deriving (Eq, Show)
@@ -1053,7 +1125,7 @@ instance ToJSON TermInclusion where
1053instance ToJSON CollectionMode where
1125instance ToJSON CollectionMode where
1054 toJSON BreadthFirst = "breadth_first"
1126 toJSON BreadthFirst = "breadth_first"
1055 toJSON DepthFirst = "depth_first"
1127 toJSON DepthFirst = "depth_first"
1057instance ToJSON ExecutionHint where
1129instance ToJSON ExecutionHint where
1058 toJSON Ordinals = "ordinals"
1130 toJSON Ordinals = "ordinals"
1059 toJSON GlobalOrdinals = "global_ordinals"
1131 toJSON GlobalOrdinals = "global_ordinals"
@@ -1083,7 +1155,7 @@ instance ToJSON Aggregation where
1083 toJSON (TermsAgg (TermsAggregation term include exclude order minDocCount size shardSize collectMode executionHint termAggs)) =
1155 toJSON (TermsAgg (TermsAggregation term include exclude order minDocCount size shardSize collectMode executionHint termAggs)) =
1084 omitNulls ["terms" .= omitNulls [ toJSON' term,
1156 omitNulls ["terms" .= omitNulls [ toJSON' term,
1085 "include" .= toJSON include,
1157 "include" .= toJSON include,
1086− "exclude" .= toJSON exclude,
1158+ "exclude" .= toJSON exclude,
1087 "order" .= toJSON order,
1159 "order" .= toJSON order,
1088 "min_doc_count" .= toJSON minDocCount,
1160 "min_doc_count" .= toJSON minDocCount,
1089 "size" .= toJSON size,
1161 "size" .= toJSON size,
@@ -1116,10 +1188,10 @@ class BucketAggregation a where
1117data (FromJSON a, BucketAggregation a) => Bucket a = Bucket { buckets :: [a]} deriving (Show)
1189data (FromJSON a, BucketAggregation a) => Bucket a = Bucket { buckets :: [a]} deriving (Show)
1119−data TermsResult = TermsResult { termKey :: Text
1191+data TermsResult = TermsResult { termKey :: Text
1120− , termsDocCount :: Int
1192+ , termsDocCount :: Int
1121− , termsAggs :: Maybe AggregationResults } deriving (Show)
1193+ , termsAggs :: Maybe AggregationResults } deriving (Show)
1123data DateHistogramResult = DateHistogramResult { dateKey :: Int
1195data DateHistogramResult = DateHistogramResult { dateKey :: Int
1124 , dateKeyStr :: Maybe Text
1196 , dateKeyStr :: Maybe Text
1125 , dateDocCount :: Int
1197 , dateDocCount :: Int
@@ -1158,7 +1230,7 @@ instance FromJSON TermsResult where
1158instance FromJSON DateHistogramResult where
1230instance FromJSON DateHistogramResult where
1159 parseJSON (Object v) = DateHistogramResult <$>
1231 parseJSON (Object v) = DateHistogramResult <$>
1160 v .: "key" <*>
1232 v .: "key" <*>
1161− v .:? "key_as_string" <*>
1233+ v .:? "key_as_string" <*>
1162 v .: "doc_count" <*>
1234 v .: "doc_count" <*>
1163 v .:? "aggregations"
1235 v .:? "aggregations"
1164 parseJSON _ = mempty
1236 parseJSON _ = mempty
@@ -1304,7 +1376,7 @@ instance ToJSON Query where
1304 object [ "match" .= toJSON matchQuery ]
1376 object [ "match" .= toJSON matchQuery ]
1306 toJSON (QueryMultiMatchQuery multiMatchQuery) =
1378 toJSON (QueryMultiMatchQuery multiMatchQuery) =
1307− object [ "multi_match" .= toJSON multiMatchQuery ]
1379+ toJSON multiMatchQuery
1309 toJSON (QueryBoolQuery boolQuery) =
1381 toJSON (QueryBoolQuery boolQuery) =
1310 object [ "bool" .= toJSON boolQuery ]
1382 object [ "bool" .= toJSON boolQuery ]
@@ -1756,15 +1828,97 @@ instance (FromJSON a) => FromJSON (EsResult a) where
1758instance ToJSON Search where
1830instance ToJSON Search where
1759− toJSON (Search query sFilter sort searchAggs sTrackSortScores sFrom sSize) =
1831+ toJSON (Search query sFilter sort searchAggs highlight sTrackSortScores sFrom sSize) =
1760− omitNulls [ "query" .= query
1832+ omitNulls [ "query" .= query
1761− , "filter" .= sFilter
1833+ , "filter" .= sFilter
1762− , "sort" .= sort
1834+ , "sort" .= sort
1763 , "aggregations" .= searchAggs
1835 , "aggregations" .= searchAggs
1836+ , "highlight" .= highlight
1764− , "from" .= sFrom
1837+ , "from" .= sFrom
1765− , "size" .= sSize
1838+ , "size" .= sSize
1766− , "track_scores" .= sTrackSortScores ]
1839+ , "track_scores" .= sTrackSortScores]
1842+instance ToJSON FieldHighlight where
1843+ toJSON (FieldHighlight (FieldName fName) (Just fSettings)) =
1844+ object [ fName .= fSettings ]
1845+ toJSON (FieldHighlight (FieldName fName) Nothing) =
1846+ object [ fName .= emptyObject ]
1848+instance ToJSON Highlights where
1849+ toJSON (Highlights global fields) =
1850+ omitNulls (("fields" .= toJSON fields)
1851+ : highlightSettingsPairs global)
1853+instance ToJSON HighlightSettings where
1854+ toJSON hs = omitNulls (highlightSettingsPairs (Just hs))
1856+highlightSettingsPairs :: Maybe HighlightSettings -> [Pair]
1857+highlightSettingsPairs Nothing = []
1858+highlightSettingsPairs (Just (Plain plh)) = plainHighPairs (Just plh)
1859+highlightSettingsPairs (Just (Postings ph)) = postHighPairs (Just ph)
1860+highlightSettingsPairs (Just (FastVector fvh)) = fastVectorHighPairs (Just fvh)
1863+plainHighPairs :: Maybe PlainHighlight -> [Pair]
1864+plainHighPairs Nothing = []
1865+plainHighPairs (Just (PlainHighlight plCom plNonPost)) =
1866+ [ "type" .= String "plain"]
1867+ ++ commonHighlightPairs plCom
1868+ ++ nonPostingsToPairs plNonPost
1870+postHighPairs :: Maybe PostingsHighlight -> [Pair]
1871+postHighPairs Nothing = []
1872+postHighPairs (Just (PostingsHighlight pCom)) =
1873+ ("type" .= String "postings")
1874+ : commonHighlightPairs pCom
1876+fastVectorHighPairs :: Maybe FastVectorHighlight -> [Pair]
1877+fastVectorHighPairs Nothing = []
1878+fastVectorHighPairs (Just
1879+ (FastVectorHighlight fvCom fvNonPostSettings fvBoundChars
1880+ fvBoundMaxScan fvFragOff fvMatchedFields
1882+ [ "type" .= String "fvh"
1883+ , "boundary_chars" .= fvBoundChars
1884+ , "boundary_max_scan" .= fvBoundMaxScan
1885+ , "fragment_offset" .= fvFragOff
1886+ , "matched_fields" .= fvMatchedFields
1887+ , "phraseLimit" .= fvPhraseLim]
1888+ ++ commonHighlightPairs fvCom
1889+ ++ nonPostingsToPairs fvNonPostSettings
1891+commonHighlightPairs :: Maybe CommonHighlight -> [Pair]
1892+commonHighlightPairs Nothing = []
1893+commonHighlightPairs (Just (CommonHighlight chScore chForceSource chTag chEncoder
1894+ chNoMatchSize chHighlightQuery
1895+ chRequireFieldMatch)) =
1896+ [ "order" .= chScore
1897+ , "force_source" .= chForceSource
1898+ , "encoder" .= chEncoder
1899+ , "no_match_size" .= chNoMatchSize
1900+ , "highlight_query" .= chHighlightQuery
1901+ , "require_fieldMatch" .= chRequireFieldMatch]
1902+ ++ highlightTagToPairs chTag
1905+nonPostingsToPairs :: Maybe NonPostings -> [Pair]
1906+nonPostingsToPairs Nothing = []
1907+nonPostingsToPairs (Just (NonPostings npFragSize npNumOfFrags)) =
1908+ [ "fragment_size" .= npFragSize
1909+ , "number_of_fragments" .= npNumOfFrags]
1913+instance ToJSON HighlightEncoder where
1914+ toJSON DefaultEncoder = String "default"
1915+ toJSON HTMLEncoder = String "html"
1917+highlightTagToPairs :: Maybe HighlightTag -> [Pair]
1918+highlightTagToPairs (Just (TagSchema _)) = [ "scheme" .= String "default"]
1919+highlightTagToPairs (Just (CustomTags (pre, post))) = [ "pre_tags" .= pre
1920+ , "post_tags" .= post]
1921+highlightTagToPairs Nothing = []
1769instance ToJSON SortSpec where
1923instance ToJSON SortSpec where
1770 toJSON (DefaultSortSpec
1924 toJSON (DefaultSortSpec
@@ -1914,15 +2068,16 @@ instance (FromJSON a) => FromJSON (SearchHits a) where
1915instance (FromJSON a) => FromJSON (Hit a) where
2069instance (FromJSON a) => FromJSON (Hit a) where
1916 parseJSON (Object v) = Hit <$>
2070 parseJSON (Object v) = Hit <$>
1917− v .: "_index" <*>
2071+ v .: "_index" <*>
1918− v .: "_type" <*>
2072+ v .: "_type" <*>
1919− v .: "_id" <*>
2073+ v .: "_id" <*>
1920− v .: "_score" <*>
2074+ v .: "_score" <*>
1921− v .: "_source"
2075+ v .: "_source" <*>
1922 parseJSON _ = empty
2077 parseJSON _ = empty
1924instance FromJSON ShardResult where
2079instance FromJSON ShardResult where
1925− parseJSON (Object v) = ShardResult <$>
2080+ parseJSON (Object v) = ShardResult <$>
1926 v .: "total" <*>
2081 v .: "total" <*>
1927 v .: "successful" <*>
2082 v .: "successful" <*>
1928 v .: "failed"
2083 v .: "failed"