@@ -1,4 +1,4 @@
1−{-# LANGUAGE DeriveGeneric #-}
1+{-# LANGUAGE DeriveGeneric, ExistentialQuantification #-}
22
33module Database.Bloodhound.Client
44 ( createIndex
@@ -49,6 +49,9 @@ module Database.Bloodhound.Client
4949 , Regexp(..)
5050 , RegexpFlags(..)
5151 , FieldName(..)
52+ , IndexName(..)
53+ , MappingName(..)
54+ , DocId(..)
5255 , CacheName(..)
5356 , CacheKey(..)
5457 )
@@ -146,8 +149,6 @@ dispatch url method body = do
146149 , checkStatus = \_ _ _ -> Nothing}
147150 withManager $ httpLbs req
148151
149−type IndexName = String
150−
151152joinPath :: [String] -> String
152153joinPath = intercalate "/"
153154
@@ -158,14 +159,14 @@ getStatus (Server server) = do
158159 return $ decode (responseBody response)
159160
160161createIndex :: Server -> IndexSettings -> IndexName -> IO Reply
161−createIndex (Server server) indexSettings indexName =
162+createIndex (Server server) indexSettings (IndexName indexName) =
162163 dispatch url method body where
163164 url = joinPath [server, indexName]
164165 method = NHTM.methodPut
165166 body = Just $ encode indexSettings
166167
167168deleteIndex :: Server -> IndexName -> IO Reply
168−deleteIndex (Server server) indexName =
169+deleteIndex (Server server) (IndexName indexName) =
169170 dispatch url method body where
170171 url = joinPath [server, indexName]
171172 method = NHTM.methodDelete
@@ -179,13 +180,13 @@ existentialQuery url = do
179180 return (reply, respIsTwoHunna reply)
180181
181182indexExists :: Server -> IndexName -> IO Bool
182−indexExists (Server server) indexName = do
183+indexExists (Server server) (IndexName indexName) = do
183184 (reply, exists) <- existentialQuery url
184185 return exists where
185186 url = joinPath [server, indexName]
186187
187188refreshIndex :: Server -> IndexName -> IO Reply
188−refreshIndex (Server server) indexName = dispatch url method body where
189+refreshIndex (Server server) (IndexName indexName) = dispatch url method body where
189190 url = joinPath [server, indexName, "_refresh"]
190191 method = NHTM.methodPost
191192 body = Nothing
@@ -197,7 +198,7 @@ stringifyOCIndex oci = case oci of
197198 CloseIndex -> "_close"
198199
199200openOrCloseIndexes :: OpenCloseIndex -> Server -> IndexName -> IO Reply
200−openOrCloseIndexes oci (Server server) indexName =
201+openOrCloseIndexes oci (Server server) (IndexName indexName) =
201202 dispatch url method body where
202203 ociString = stringifyOCIndex oci
203204 url = joinPath [server, indexName, ociString]
@@ -210,8 +211,6 @@ openIndex = openOrCloseIndexes OpenIndex
210211closeIndex :: Server -> IndexName -> IO Reply
211212closeIndex = openOrCloseIndexes CloseIndex
212213
213−type MappingName = String
214−
215214data FieldType = GeoPointType
216215 | GeoShapeType
217216 | FloatType
@@ -232,37 +231,56 @@ data Mapping = Mapping { typeName :: Text
232231
233232createMapping :: ToJSON a => Server -> IndexName
234233 -> MappingName -> a -> IO Reply
235−createMapping (Server server) indexName mappingName mapping =
234+createMapping (Server server) (IndexName indexName) (MappingName mappingName) mapping =
236235 dispatch url method body where
237236 url = joinPath [server, indexName, mappingName, "_mapping"]
238237 method = NHTM.methodPut
239238 body = Just $ encode mapping
240239
241240deleteMapping :: Server -> IndexName -> MappingName -> IO Reply
242−deleteMapping (Server server) indexName mappingName =
241+deleteMapping (Server server) (IndexName indexName) (MappingName mappingName) =
243242 dispatch url method body where
244243 url = joinPath [server, indexName, mappingName, "_mapping"]
245244 method = NHTM.methodDelete
246245 body = Nothing
247246
248−type DocumentID = String
249−
250247indexDocument :: ToJSON doc => Server -> IndexName -> MappingName
251− -> doc -> DocumentID -> IO Reply
252−indexDocument (Server server) indexName mappingName document docId =
248+ -> doc -> DocId -> IO Reply
249+indexDocument (Server server) (IndexName indexName)
250+ (MappingName mappingName) document (DocId docId) =
253251 dispatch url method body where
254252 url = joinPath [server, indexName, mappingName, docId]
255253 method = NHTM.methodPut
256254 body = Just (encode document)
257255
258256deleteDocument :: Server -> IndexName -> MappingName
259− -> DocumentID -> IO Reply
260−deleteDocument (Server server) indexName mappingName docId =
257+ -> DocId -> IO Reply
258+deleteDocument (Server server) (IndexName indexName)
259+ (MappingName mappingName) (DocId docId) =
261260 dispatch url method body where
262261 url = joinPath [server, indexName, mappingName, docId]
263262 method = NHTM.methodDelete
264263 body = Nothing
265264
265+-- bulk :: Server -> [BulkOperation a] -> IO Reply
266+-- bulk (Server server) bulkOps = dispatch url method body where
267+-- url = joinPath [server, "_bulk"]
268+-- method = NHTM.methodPost
269+-- body = Just (L.intercalate "\n" . fmap encode $ bulkOps)
270+
271+data BulkOperation a =
272+ forall a. ToJSON a =>
273+ BulkIndex (AssociatedDocument a)
274+ | BulkCreate (AssociatedDocument a)
275+ | BulkDelete Association
276+ | BulkUpdate (AssociatedDocument a)
277+
278+data Placement = Placement IndexName MappingName deriving (Eq, Show)
279+data Association = Association Placement DocId deriving (Eq, Show)
280+
281+data AssociatedDocument a =
282+ forall a. ToJSON a => Associate Association a
283+
266284data EsResult a = EsResult { _index :: Text
267285 , _type :: Text
268286 , _id :: Text
@@ -281,16 +299,16 @@ instance (FromJSON a, ToJSON a) => FromJSON (EsResult a) where
281299 parseJSON _ = empty
282300
283301getDocument :: Server -> IndexName -> MappingName
284− -> DocumentID -> IO Reply
285−getDocument (Server server) indexName mappingName docId =
302+ -> DocId -> IO Reply
303+getDocument (Server server) (IndexName indexName) (MappingName mappingName) (DocId docId) =
286304 dispatch url method body where
287305 url = joinPath [server, indexName, mappingName, docId]
288306 method = NHTM.methodGet
289307 body = Nothing
290308
291309documentExists :: Server -> IndexName -> MappingName
292− -> DocumentID -> IO Bool
293−documentExists (Server server) indexName mappingName docId = do
310+ -> DocId -> IO Bool
311+documentExists (Server server) (IndexName indexName) (MappingName mappingName) (DocId docId) = do
294312 (reply, exists) <- existentialQuery url
295313 return exists where
296314 url = joinPath [server, indexName, mappingName, docId]
@@ -304,11 +322,12 @@ searchAll (Server server) search = dispatchSearch url search where
304322 url = joinPath [server, "_search"]
305323
306324searchByIndex :: Server -> IndexName -> Search -> IO Reply
307−searchByIndex (Server server) indexName search = dispatchSearch url search where
325+searchByIndex (Server server) (IndexName indexName) search = dispatchSearch url search where
308326 url = joinPath [server, indexName, "_search"]
309327
310328searchByType :: Server -> IndexName -> MappingName -> Search -> IO Reply
311−searchByType (Server server) indexName mappingName search = dispatchSearch url search where
329+searchByType (Server server) (IndexName indexName)
330+ (MappingName mappingName) search = dispatchSearch url search where
312331 url = joinPath [server, indexName, mappingName, "_search"]
313332
314333data Search = Search { queryBody :: Maybe Query
@@ -457,12 +476,22 @@ type PrefixValue = Text
457476
458477data BooleanOperator = And | Or deriving (Eq, Show)
459478
479+newtype IndexName = IndexName String deriving (Eq, Generic, Show)
480+newtype MappingName = MappingName String deriving (Eq, Generic, Show)
481+newtype DocId = DocId String deriving (Eq, Generic, Show)
460482newtype QueryString = QueryString Text deriving (Eq, Show)
461−newtype FieldName = FieldName Text deriving (Eq, Show)
462−newtype CacheName = CacheName Text deriving (Eq, Show)
463−newtype CacheKey = CacheKey Text deriving (Eq, Show)
464−newtype Existence = Existence Bool deriving (Eq, Show)
465−newtype NullValue = NullValue Bool deriving (Eq, Show)
483+newtype FieldName = FieldName Text deriving (Eq, Show)
484+newtype CacheName = CacheName Text deriving (Eq, Show)
485+newtype CacheKey = CacheKey Text deriving (Eq, Show)
486+newtype Existence = Existence Bool deriving (Eq, Show)
487+newtype NullValue = NullValue Bool deriving (Eq, Show)
488+
489+unpackId :: DocId -> String
490+unpackId (DocId docId) = docId
491+
492+instance FromJSON IndexName
493+instance FromJSON MappingName
494+instance FromJSON DocId
466495
467496-- data QueryType = BooleanQueryType
468497-- | PhraseQueryType
@@ -495,7 +524,7 @@ data Filter = AndFilter [Filter] Cache
495524 | GeoDistanceFilter GeoPoint Distance DistanceType OptimizeBbox Cache
496525 | GeoDistanceRangeFilter GeoPoint DistanceRange
497526 | GeoPolygonFilter FieldName [LatLon]
498− | IdsFilter MappingName [DocumentID]
527+ | IdsFilter MappingName [DocId]
499528 | LimitFilter Int
500529 | MissingFilter FieldName Existence NullValue
501530 | PrefixFilter FieldName PrefixValue Cache
@@ -568,10 +597,10 @@ instance ToJSON Filter where
568597 object [geoField .=
569598 object ["points" .= fmap toJSON latLons]]]
570599
571− toJSON (IdsFilter mappingName values) =
600+ toJSON (IdsFilter (MappingName mappingName) values) =
572601 object ["ids" .=
573602 object ["type" .= mappingName
574− , "values" .= fmap T.pack values]]
603+ , "values" .= fmap (T.pack . unpackId) values]]
575604
576605 toJSON (LimitFilter limit) =
577606 object ["limit" .= object ["value" .= limit]]
@@ -815,7 +844,7 @@ data FromJSON a => SearchHits a =
815844data FromJSON a => Hit a =
816845 Hit { hitIndex :: IndexName
817846 , hitType :: MappingName
818− , hitDocumentID :: DocumentID
847+ , hitDocId :: DocId
819848 , hitScore :: Score
820849 , hitSource :: a } deriving (Eq, Show)
821850