git.iko.soy/typeable/bloodhound
on master help sign in
Implement index optimization
commit1889edd4b4f2dc4872dd198e29a98b94f5cd0a21 authorMichael Xavier <michael@michaelxavier.net> dateWed 27 Jan 2016, 10:43 (11 years ago) parent194582d
3 files changed+84−2
src/Database/Bloodhound/Client.hs+47−2 src/Database/Bloodhound/Types.hs+31 tests/tests.hs+6
src/Database/Bloodhound/Client.hs+47−2
@@ -1,5 +1,6 @@
11{-# LANGUAGE OverloadedStrings #-}
22{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE TupleSections #-}
34
45-------------------------------------------------------------------------------
56-- |
@@ -26,6 +27,7 @@ module Database.Bloodhound.Client
2627 , deleteIndex
2728 , updateIndexSettings
2829 , getIndexSettings
30+ , optimizeIndex
2931 , indexExists
3032 , openIndex
3133 , closeIndex
@@ -81,7 +83,7 @@ import qualified Data.HashMap.Strict as HM
8183import Data.Ix
8284import qualified Data.List as LS (filter, foldl')
8385import Data.List.NonEmpty (NonEmpty (..))
84−import Data.Maybe (fromMaybe, isJust)
86+import Data.Maybe (catMaybes, fromMaybe, isJust)
8587import Data.Monoid
8688import Data.Text (Text)
8789import qualified Data.Text as T
@@ -302,6 +304,48 @@ getIndexSettings (IndexName indexName) = do
302304 where url = joinPath [indexName, "_settings"]
303305
304306
307+-- | 'optimizeIndex' will optimize a single index, list of indexes or
308+-- all indexes. Note that this call will block until finishing but
309+-- will continue even if the request times out. Concurrent requests to
310+-- optimize an index while another is performing will block until the
311+-- previous one finishes. For more information see
312+-- <https://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-optimize.html>. Nothing
313+-- worthwhile comes back in the reply body, so matching on the status
314+-- should suffice.
315+--
316+-- 'optimizeIndex' with a maxNumSegments of 1 and onlyExpungeDeletes
317+-- to True is the main way to release disk space back to the OS being
318+-- held by deleted documents.
319+--
320+-- Note that this API was deprecated in ElasticSearch 2.1 for the
321+-- almost completely identical forcemerge API. Adding support to that
322+-- API would be trivial but due to the significant breaking changes,
323+-- this library cannot currently be used with >= 2.0, so that feature was omitted.
324+--
325+-- >>> let ixn = IndexName "unoptimizedindex"
326+-- >>> _ <- runBH' $ deleteIndex ixn >> createIndex defaultIndexSettings ixn
327+-- >>> response <- runBH' $ optimizeIndex (IndexList (ixn :| [])) (defaultIndexOptimizationSettings { maxNumSegments = Just 1, onlyExpungeDeletes = True })
328+-- >>> respIsTwoHunna response
329+-- True
330+optimizeIndex :: MonadBH m => IndexSelection -> IndexOptimizationSettings -> m Reply
331+optimizeIndex ixs IndexOptimizationSettings {..} =
332+ bindM2 post url (return body)
333+ where url = addQuery params <$> joinPath [indexName, "_optimize"]
334+ params = catMaybes [ ("max_num_segments",) . Just . showText <$> maxNumSegments
335+ , Just ("only_expunge_deletes", Just (boolQP onlyExpungeDeletes))
336+ , Just ("flush", Just (boolQP flushAfterOptimize))
337+ ]
338+ indexName = indexSelectionName ixs
339+ boolQP True = "true"
340+ boolQP False = "false"
341+ body = Nothing
342+
343+
344+-------------------------------------------------------------------------------
345+indexSelectionName :: IndexSelection -> Text
346+indexSelectionName (IndexList names) = T.intercalate "," [n | IndexName n <- toList names]
347+indexSelectionName AllIndexes = "_all"
348+
305349deepMerge :: [Object] -> Object
306350deepMerge = LS.foldl' go mempty
307351 where go acc = LS.foldl' go' acc . HM.toList
@@ -395,6 +439,7 @@ closeIndex = openOrCloseIndexes CloseIndex
395439-- >>> let aliasName = IndexName "an-alias"
396440-- >>> let iAlias = IndexAlias src (IndexAliasName aliasName)
397441-- >>> let aliasCreate = IndexAliasCreate Nothing Nothing
442+-- >>> _ <- runBH' $ deleteIndex src
398443-- >>> respIsTwoHunna <$> runBH' (createIndex defaultIndexSettings src)
399444-- True
400445-- >>> runBH' $ indexExists src
@@ -484,7 +529,7 @@ versionCtlParams cfg =
484529 ExternalGTE (ExternalDocVersion v) -> versionParams v "external_gte"
485530 ForceVersion (ExternalDocVersion v) -> versionParams v "force"
486531 where
487− vt = T.pack . show . docVersionNumber
532+ vt = showText . docVersionNumber
488533 versionParams v t = [ ("version", Just $ vt v)
489534 , ("version_type", Just t)
490535 ]
src/Database/Bloodhound/Types.hs+31
@@ -140,6 +140,9 @@ module Database.Bloodhound.Types
140140 , FieldName(..)
141141 , Script(..)
142142 , IndexName(..)
143+ , IndexSelection(..)
144+ , IndexOptimizationSettings(..)
145+ , defaultIndexOptimizationSettings
143146 , TemplateName(..)
144147 , TemplatePattern(..)
145148 , MappingName(..)
@@ -381,6 +384,28 @@ data IndexSettings =
381384defaultIndexSettings :: IndexSettings
382385defaultIndexSettings = IndexSettings (ShardCount 3) (ReplicaCount 2)
383386
387+
388+{-| 'IndexOptimizationSettings' is used to configure index optimization. See
389+ <https://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-optimize.html>
390+ for more info.
391+-}
392+data IndexOptimizationSettings =
393+ IndexOptimizationSettings { maxNumSegments :: Maybe Int
394+ -- ^ Number of segments to optimize to. 1 will fully optimize the index. If omitted, the default behavior is to only optimize if the server deems it necessary.
395+ , onlyExpungeDeletes :: Bool
396+ -- ^ Should the optimize process only expunge segments with deletes in them? If the purpose of the optimization is to free disk space, this should be set to True.
397+ , flushAfterOptimize :: Bool
398+ -- ^ Should a flush be performed after the optimize.
399+ } deriving (Eq, Show, Generic, Typeable)
400+
401+
402+{-| 'defaultIndexOptimizationSettings' implements the default settings that
403+ ElasticSearch uses for index optimization. 'maxNumSegments' is Nothing,
404+ 'onlyExpungeDeletes' is False, and flushAfterOptimize is True.
405+-}
406+defaultIndexOptimizationSettings :: IndexOptimizationSettings
407+defaultIndexOptimizationSettings = IndexOptimizationSettings Nothing False True
408+
384409{-| 'UpdatableIndexSetting' are settings which may be updated after an index is created.
385410
386411 <https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html>
@@ -764,6 +789,12 @@ newtype ReplicaCount = ReplicaCount Int deriving (Eq, Show, Generic, ToJSON, Typ
764789-}
765790newtype IndexName = IndexName Text deriving (Eq, Generic, Show, ToJSON, FromJSON, Typeable)
766791
792+{-| 'IndexSelection' is used for APIs which take a single index, a list of
793+ indexes, or the special @_all@ index.
794+-}
795+data IndexSelection = IndexList (NonEmpty IndexName)
796+ | AllIndexes deriving (Eq, Generic, Show, Typeable)
797+
767798{-| 'TemplateName' is used to describe which template to query/create/delete
768799-}
769800newtype TemplateName = TemplateName Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Typeable)
tests/tests.hs+6
@@ -1416,6 +1416,12 @@ main = hspec $ do
14161416 (IndexSettings (ShardCount 1) (ReplicaCount 0))
14171417 (NE.toList updates))
14181418
1419+ describe "Index Optimization" $ do
1420+ it "returns a successful response upon completion" $ withTestEnv $ do
1421+ _ <- createExampleIndex
1422+ resp <- optimizeIndex (IndexList (testIndex :| [])) defaultIndexOptimizationSettings
1423+ liftIO $ validateStatus resp 200
1424+
14191425 describe "JSON instances" $ do
14201426 propJSON (Proxy :: Proxy Version)
14211427 propJSON (Proxy :: Proxy IndexName)