@@ -29,6 +29,7 @@
29module Database.Bloodhound.Types
29module Database.Bloodhound.Types
30 ( defaultCache
30 ( defaultCache
31 , defaultIndexSettings
31 , defaultIndexSettings
32+ , defaultIndexDocumentSettings
33 , showText
34 , showText
34 , unpackId
35 , unpackId
@@ -41,6 +42,8 @@ module Database.Bloodhound.Types
41 , mkTermsAggregation
42 , mkTermsAggregation
42 , mkTermsScriptAggregation
43 , mkTermsScriptAggregation
43 , mkDateHistogram
44 , mkDateHistogram
45 , toDateHistogram
48 , toDateHistogram
46 , omitNulls
49 , omitNulls
@@ -56,6 +59,10 @@ module Database.Bloodhound.Types
56 , Server(..)
59 , Server(..)
58 , EsResult(..)
61 , EsResult(..)
63+ , ExternalDocVersion(..)
65+ , IndexDocumentSettings(..)
59 , Query(..)
66 , Query(..)
60 , Search(..)
67 , Search(..)
61 , SearchResult(..)
68 , SearchResult(..)
@@ -218,10 +225,12 @@ import qualified Data.ByteString.Lazy.Char8 as L
218import Data.List (nub)
225import Data.List (nub)
219import Data.List.NonEmpty (NonEmpty (..), toList)
226import Data.List.NonEmpty (NonEmpty (..), toList)
220import qualified Data.Map.Strict as M
227import qualified Data.Map.Strict as M
221import Data.Text (Text)
229import Data.Text (Text)
222import qualified Data.Text as T
230import qualified Data.Text as T
223import Data.Time.Clock (UTCTime)
231import Data.Time.Clock (UTCTime)
224import qualified Data.Vector as V
232import qualified Data.Vector as V
225import GHC.Generics (Generic)
234import GHC.Generics (Generic)
226import Network.HTTP.Client
235import Network.HTTP.Client
227import qualified Network.HTTP.Types.Method as NHTM
236import qualified Network.HTTP.Types.Method as NHTM
@@ -371,10 +380,78 @@ data BulkOperation =
371data EsResult a = EsResult { _index :: Text
380data EsResult a = EsResult { _index :: Text
372 , _type :: Text
381 , _type :: Text
373 , _id :: Text
382 , _id :: Text
374− , _version :: Int
383+ , _version :: DocVersion
375 , found :: Maybe Bool
384 , found :: Maybe Bool
376 , _source :: a } deriving (Eq, Show)
385 , _source :: a } deriving (Eq, Show)
387+{-| 'DocVersion' is an integer version number for a document between 1
388+and 9.2e+18 used for <<https://www.elastic.co/guide/en/elasticsearch/guide/current/optimistic-concurrency-control.html optimistic concurrency control>>.
390+newtype DocVersion = DocVersion {
391+ docVersionNumber :: Int
392+ } deriving (Eq, Show, Ord, ToJSON)
394+-- | Smart constructor for in-range doc version
395+mkDocVersion :: Int -> Maybe DocVersion
397+ | i >= (docVersionNumber minBound) && i <= (docVersionNumber maxBound) =
399+ | otherwise = Nothing
402+{-| 'ExternalDocVersion' is a convenience wrapper if your code uses its
403+own version numbers instead of ones from ES.
405+newtype ExternalDocVersion = ExternalDocVersion DocVersion
406+ deriving (Eq, Show, Ord, Bounded, Enum, ToJSON)
408+{-| 'VersionControl' is specified when indexing documents as a
409+optimistic concurrency control.
411+data VersionControl = NoVersionControl
412+ -- ^ Don't send a version. This is a pure overwrite.
413+ | InternalVersion DocVersion
414+ -- ^ Use the default ES versioning scheme. Only
415+ -- index the document if the version is the same
416+ -- as the one specified. Only applicable to
417+ -- updates, as you should be getting Version from
419+ | ExternalGT ExternalDocVersion
420+ -- ^ Use your own version numbering. Only index
421+ -- the document if the version is strictly higher
422+ -- OR the document doesn't exist. The given
423+ -- version will be used as the new version number
424+ -- for the stored document. N.B. All updates must
425+ -- increment this number, meaning there is some
426+ -- global, external ordering of updates.
427+ | ExternalGTE ExternalDocVersion
428+ -- ^ Use your own version numbering. Only index
429+ -- the document if the version is equal or higher
430+ -- than the stored version. Will succeed if there
431+ -- is no existing document. The given version will
432+ -- be used as the new version number for the
433+ -- stored document. Use with care, as this could
434+ -- result in data loss.
435+ | ForceVersion ExternalDocVersion
436+ -- ^ The document will always be indexed and the
437+ -- given version will be the new version. This is
438+ -- typically used for correcting errors. Use with
439+ -- care, as this could result in data loss.
440+ deriving (Show, Eq, Ord)
442+{-| 'IndexDocumentSettings' are special settings supplied when indexing
443+a document. For the best backwards compatiblity when new fields are
444+added, you should probably prefer to start with 'defaultIndexDocumentSettings'
446+data IndexDocumentSettings = IndexDocumentSettings {
447+ idsVersionControl :: VersionControl
450+{-| Reasonable default settings. Chooses no version control.
452+defaultIndexDocumentSettings :: IndexDocumentSettings
453+defaultIndexDocumentSettings = IndexDocumentSettings NoVersionControl
378{-| 'Sort' is a synonym for a list of 'SortSpec's. Sort behavior is order
455{-| 'Sort' is a synonym for a list of 'SortSpec's. Sort behavior is order
379 dependent with later sorts acting as tie-breakers for earlier sorts.
456 dependent with later sorts acting as tie-breakers for earlier sorts.
@@ -2173,3 +2250,26 @@ instance FromJSON ShardResult where
2173 v .: "successful" <*>
2250 v .: "successful" <*>
2174 v .: "failed"
2251 v .: "failed"
2175 parseJSON _ = empty
2252 parseJSON _ = empty
2255+instance FromJSON DocVersion where
2258+ maybe (fail "DocVersion out of range") return $ mkDocVersion i
2260+instance Bounded DocVersion where
2261+ minBound = DocVersion 1
2262+ maxBound = DocVersion 9200000000000000000 -- 9.2e+18
2264+instance Enum DocVersion where
2266+ | x /= maxBound = DocVersion (succ $ docVersionNumber x)
2267+ | otherwise = succError "DocVersion"
2269+ | x /= minBound = DocVersion (pred $ docVersionNumber x)
2270+ | otherwise = predError "DocVersion"
2272+ fromMaybe (error $ show i ++ " out of DocVersion range") $ mkDocVersion i
2273+ fromEnum = docVersionNumber
2274+ enumFrom = boundedEnumFrom
2275+ enumFromThen = boundedEnumFromThen