@@ -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 ]