@@ -203,6 +203,7 @@ module Database.V5.Bloodhound.Types
203 , CutoffFrequency(..)
203 , CutoffFrequency(..)
204 , Analyzer(..)
204 , Analyzer(..)
205 , Tokenizer(..)
205 , Tokenizer(..)
206 , MaxExpansions(..)
207 , MaxExpansions(..)
207 , Lenient(..)
208 , Lenient(..)
208 , MatchQueryType(..)
209 , MatchQueryType(..)
@@ -381,8 +382,11 @@ module Database.V5.Bloodhound.Types
381 , Analysis(..)
382 , Analysis(..)
382 , AnalyzerDefinition(..)
383 , AnalyzerDefinition(..)
383 , TokenizerDefinition(..)
384 , TokenizerDefinition(..)
385+ , TokenFilterDefinition(..)
384 , Ngram(..)
386 , Ngram(..)
385 , TokenChar(..)
387 , TokenChar(..)
388import Control.Applicative as A
392import Control.Applicative as A
@@ -597,32 +601,244 @@ data UpdatableIndexSetting = NumberOfReplicas ReplicaCount
597data Analysis = Analysis
601data Analysis = Analysis
598 { analysisAnalyzer :: M.Map Text AnalyzerDefinition
602 { analysisAnalyzer :: M.Map Text AnalyzerDefinition
599 , analysisTokenizer :: M.Map Text TokenizerDefinition
603 , analysisTokenizer :: M.Map Text TokenizerDefinition
604+ , analysisTokenFilter :: M.Map Text TokenFilterDefinition
600 } deriving (Eq,Show,Generic,Typeable)
605 } deriving (Eq,Show,Generic,Typeable)
602instance ToJSON Analysis where
607instance ToJSON Analysis where
603− toJSON (Analysis analyzer tokenizer) = object
608+ toJSON (Analysis analyzer tokenizer tokenFilter) = object
604 [ "analyzer" .= analyzer
609 [ "analyzer" .= analyzer
605 , "tokenizer" .= tokenizer
610 , "tokenizer" .= tokenizer
611+ , "filter" .= tokenFilter
608instance FromJSON Analysis where
614instance FromJSON Analysis where
609 parseJSON = withObject "Analysis" $ \m -> Analysis
615 parseJSON = withObject "Analysis" $ \m -> Analysis
610 <$> m .: "analyzer"
616 <$> m .: "analyzer"
611− <*> m .: "tokenizer"
617+ <*> m .:? "tokenizer" .!= M.empty
618+ <*> m .:? "filter" .!= M.empty
613data AnalyzerDefinition = AnalyzerDefinition
620data AnalyzerDefinition = AnalyzerDefinition
614 { analyzerDefinitionTokenizer :: Maybe Tokenizer
621 { analyzerDefinitionTokenizer :: Maybe Tokenizer
622+ , analyzerDefinitionFilter :: [TokenFilter]
615 } deriving (Eq,Show,Generic,Typeable)
623 } deriving (Eq,Show,Generic,Typeable)
617instance ToJSON AnalyzerDefinition where
625instance ToJSON AnalyzerDefinition where
618− toJSON (AnalyzerDefinition tokenizer) = object $ catMaybes
626+ toJSON (AnalyzerDefinition tokenizer tokenFilter) = object $ catMaybes
619 [ fmap ("tokenizer" .=) tokenizer
627 [ fmap ("tokenizer" .=) tokenizer
628+ , Just $ "filter" .= tokenFilter
622instance FromJSON AnalyzerDefinition where
631instance FromJSON AnalyzerDefinition where
623 parseJSON = withObject "AnalyzerDefinition" $ \m -> AnalyzerDefinition
632 parseJSON = withObject "AnalyzerDefinition" $ \m -> AnalyzerDefinition
624 <$> m .:? "tokenizer"
633 <$> m .:? "tokenizer"
634+ <*> m .:? "filter" .!= []
636+-- | Token filters are used to create custom analyzers.
637+data TokenFilterDefinition
638+ = TokenFilterDefinitionLowercase Language
639+ | TokenFilterDefinitionUppercase Language
640+ | TokenFilterDefinitionApostrophe
641+ | TokenFilterDefinitionReverse
642+ | TokenFilterDefinitionSnowball Language
643+ | TokenFilterDefinitionShingle Shingle
644+ deriving (Eq,Show,Generic)
646+instance ToJSON TokenFilterDefinition where
647+ toJSON x = case x of
648+ TokenFilterDefinitionLowercase lang -> object
649+ [ "type" .= ("lowercase" :: Text)
650+ , "language" .= languageToText lang
652+ TokenFilterDefinitionUppercase lang -> object
653+ [ "type" .= ("uppercase" :: Text)
654+ , "language" .= languageToText lang
656+ TokenFilterDefinitionApostrophe -> object
657+ [ "type" .= ("apostrophe" :: Text)
659+ TokenFilterDefinitionReverse -> object
660+ [ "type" .= ("reverse" :: Text)
662+ TokenFilterDefinitionSnowball lang -> object
663+ [ "type" .= ("snowball" :: Text)
664+ , "language" .= languageToText lang
666+ TokenFilterDefinitionShingle s -> object
667+ [ "type" .= ("shingle" :: Text)
668+ , "max_shingle_size" .= shingleMaxSize s
669+ , "min_shingle_size" .= shingleMinSize s
670+ , "output_unigrams" .= shingleOutputUnigrams s
671+ , "output_unigrams_if_no_shingles" .= shingleOutputUnigramsIfNoShingles s
672+ , "token_separator" .= shingleTokenSeparator s
673+ , "filler_token" .= shingleFillerToken s
676+instance FromJSON TokenFilterDefinition where
677+ parseJSON = withObject "TokenFilterDefinition" $ \m -> do
680+ "reverse" -> return TokenFilterDefinitionReverse
681+ "apostrophe" -> return TokenFilterDefinitionApostrophe
682+ "lowercase" -> TokenFilterDefinitionLowercase
683+ <$> m .:? "language" .!= English
684+ "uppercase" -> TokenFilterDefinitionUppercase
685+ <$> m .:? "language" .!= English
686+ "snowball" -> TokenFilterDefinitionSnowball
687+ <$> m .:? "language" .!= English
688+ "shingle" -> fmap TokenFilterDefinitionShingle $ Shingle
689+ <$> (fmap.fmap) unStringlyTypedInt (m .:? "max_shingle_size") .!= 2
690+ <*> (fmap.fmap) unStringlyTypedInt (m .:? "min_shingle_size") .!= 2
691+ <*> (fmap.fmap) unStringlyTypedBool (m .:? "output_unigrams") .!= True
692+ <*> (fmap.fmap) unStringlyTypedBool (m .:? "output_unigrams_if_no_shingles") .!= False
693+ <*> m .:? "token_separator" .!= " "
694+ <*> m .:? "filler_token" .!= "_"
695+ _ -> fail ("unrecognized token filter type: " ++ T.unpack t)
697+-- | The set of languages that can be passed to various analyzers,
698+-- filters, etc. in ElasticSearch. Most data types in this module
699+-- that have a 'Language' field are actually only actually to
700+-- handle a subset of these languages. Consult the official
701+-- ElasticSearch documentation to see what is actually supported.
741+ deriving (Show,Eq,Generic)
743+instance ToJSON Language where
744+ toJSON = Data.Aeson.String . languageToText
746+instance FromJSON Language where
747+ parseJSON = withText "Language" $ \t -> case languageFromText t of
748+ Nothing -> fail "not a supported ElasticSearch language"
749+ Just lang -> return lang
751+languageToText :: Language -> Text
752+languageToText x = case x of
754+ Armenian -> "armenian"
756+ Bengali -> "bengali"
757+ Brazilian -> "brazilian"
758+ Bulgarian -> "bulgarian"
759+ Catalan -> "catalan"
764+ English -> "english"
765+ Finnish -> "finnish"
767+ Galician -> "galician"
769+ German2 -> "german2"
772+ Hungarian -> "hungarian"
773+ Indonesian -> "indonesian"
775+ Italian -> "italian"
777+ Latvian -> "latvian"
778+ Lithuanian -> "lithuanian"
780+ Norwegian -> "norwegian"
781+ Persian -> "persian"
783+ Portuguese -> "portuguese"
784+ Romanian -> "romanian"
785+ Russian -> "russian"
787+ Spanish -> "spanish"
788+ Swedish -> "swedish"
790+ Turkish -> "turkish"
792+languageFromText :: Text -> Maybe Language
793+languageFromText x = case x of
794+ "arabic" -> Just Arabic
795+ "armenian" -> Just Armenian
796+ "basque" -> Just Basque
797+ "bengali" -> Just Bengali
798+ "brazilian" -> Just Brazilian
799+ "bulgarian" -> Just Bulgarian
800+ "catalan" -> Just Catalan
802+ "czech" -> Just Czech
803+ "danish" -> Just Danish
804+ "dutch" -> Just Dutch
805+ "english" -> Just English
806+ "finnish" -> Just Finnish
807+ "french" -> Just French
808+ "galician" -> Just Galician
809+ "german" -> Just German
810+ "german2" -> Just German2
811+ "greek" -> Just Greek
812+ "hindi" -> Just Hindi
813+ "hungarian" -> Just Hungarian
814+ "indonesian" -> Just Indonesian
815+ "irish" -> Just Irish
816+ "italian" -> Just Italian
818+ "latvian" -> Just Latvian
819+ "lithuanian" -> Just Lithuanian
820+ "lovins" -> Just Lovins
821+ "norwegian" -> Just Norwegian
822+ "persian" -> Just Persian
823+ "porter" -> Just Porter
824+ "portuguese" -> Just Portuguese
825+ "romanian" -> Just Romanian
826+ "russian" -> Just Russian
827+ "sorani" -> Just Sorani
828+ "spanish" -> Just Spanish
829+ "swedish" -> Just Swedish
831+ "turkish" -> Just Turkish
834+data Shingle = Shingle
835+ { shingleMaxSize :: Int
836+ , shingleMinSize :: Int
837+ , shingleOutputUnigrams :: Bool
838+ , shingleOutputUnigramsIfNoShingles :: Bool
839+ , shingleTokenSeparator :: Text
840+ , shingleFillerToken :: Text
841+ } deriving (Eq,Show,Generic,Typeable)
627data TokenizerDefinition
843data TokenizerDefinition
628 = TokenizerDefinitionNgram Ngram
844 = TokenizerDefinitionNgram Ngram
@@ -1110,6 +1326,8 @@ newtype Analyzer =
1110 Analyzer Text deriving (Eq, Read, Show, Generic, ToJSON, FromJSON, Typeable)
1326 Analyzer Text deriving (Eq, Read, Show, Generic, ToJSON, FromJSON, Typeable)
1111newtype Tokenizer =
1327newtype Tokenizer =
1112 Tokenizer Text deriving (Eq, Read, Show, Generic, ToJSON, FromJSON, Typeable)
1328 Tokenizer Text deriving (Eq, Read, Show, Generic, ToJSON, FromJSON, Typeable)
1329+newtype TokenFilter =
1330+ TokenFilter Text deriving (Eq, Read, Show, Generic, ToJSON, FromJSON, Typeable)
1113newtype MaxExpansions =
1331newtype MaxExpansions =
1114 MaxExpansions Int deriving (Eq, Read, Show, Generic, ToJSON, FromJSON, Typeable)
1332 MaxExpansions Int deriving (Eq, Read, Show, Generic, ToJSON, FromJSON, Typeable)
@@ -4751,6 +4969,11 @@ newtype StringlyTypedInt = StringlyTypedInt { unStringlyTypedInt :: Int }
4751instance FromJSON StringlyTypedInt where
4969instance FromJSON StringlyTypedInt where
4752 parseJSON = fmap StringlyTypedInt . parseJSON . unStringlyTypeJSON
4970 parseJSON = fmap StringlyTypedInt . parseJSON . unStringlyTypeJSON
4972+newtype StringlyTypedBool = StringlyTypedBool { unStringlyTypedBool :: Bool }
4974+instance FromJSON StringlyTypedBool where
4975+ parseJSON = fmap StringlyTypedBool . parseJSON . unStringlyTypeJSON
4754instance FromJSON NodeFSTotalStats where
4977instance FromJSON NodeFSTotalStats where
4755 parseJSON = withObject "NodeFSTotalStats" parse
4978 parseJSON = withObject "NodeFSTotalStats" parse