1module Database.Bloodhound.Client
27import qualified Data.ByteString.Lazy.Char8 as L
28import Data.ByteString.Builder
29import Data.List (foldl', intercalate, intersperse)
30import Data.Maybe (fromMaybe)
31import Data.Text (Text)
32import Network.HTTP.Client
33import qualified Network.HTTP.Types.Method as NHTM
34import qualified Network.HTTP.Types.Status as NHTS
35import Prelude hiding (head, filter)
37import Database.Bloodhound.Types
38import Database.Bloodhound.Types.Instances
40-- find way to avoid destructuring Servers and Indexes?
41-- make get, post, put, delete helpers.
42-- make dispatch take URL last for better variance and
43-- utilization of partial application
45mkShardCount :: Int -> Maybe ShardCount
48 | n > 1000 = Nothing -- seriously, what the fuck?
49 | otherwise = Just (ShardCount n)
51mkReplicaCount :: Int -> Maybe ReplicaCount
54 | n > 1000 = Nothing -- ...
55 | otherwise = Just (ReplicaCount n)
57emptyBody :: L.ByteString
60dispatch :: Method -> String -> Maybe L.ByteString
62dispatch dMethod url body = do
63 initReq <- parseUrl url
64 let reqBody = RequestBodyLBS $ fromMaybe emptyBody body
65 let req = initReq { method = dMethod
66 , requestBody = reqBody
67 , checkStatus = \_ _ _ -> Nothing}
68 withManager defaultManagerSettings $ httpLbs req
70joinPath :: [String] -> String
71joinPath = intercalate "/"
73-- Shortcut functions for HTTP methods
74delete :: String -> IO Reply
75delete = flip (dispatch NHTM.methodDelete) Nothing
76get :: String -> IO Reply
77get = flip (dispatch NHTM.methodGet) Nothing
78head :: String -> IO Reply
79head = flip (dispatch NHTM.methodHead) Nothing
80put :: String -> Maybe L.ByteString -> IO Reply
81put = dispatch NHTM.methodPost
82post :: String -> Maybe L.ByteString -> IO Reply
83post = dispatch NHTM.methodPost
85-- indexDocument s ix name doc = put (root </> s </> ix </> name </> doc) (Just encode doc)
86-- http://hackage.haskell.org/package/http-client-lens-0.1.0/docs/Network-HTTP-Client-Lens.html
87-- https://github.com/supki/libjenkins/blob/master/src/Jenkins/Rest/Internal.hs
89getStatus :: Server -> IO (Maybe Status)
90getStatus (Server server) = do
91 request <- parseUrl $ joinPath [server]
92 response <- withManager defaultManagerSettings $ httpLbs request
93 return $ decode (responseBody response)
95createIndex :: Server -> IndexSettings -> IndexName -> IO Reply
96createIndex (Server server) indexSettings (IndexName indexName) =
98 where url = joinPath [server, indexName]
99 body = Just $ encode indexSettings
101deleteIndex :: Server -> IndexName -> IO Reply
102deleteIndex (Server server) (IndexName indexName) =
103 delete $ joinPath [server, indexName]
105respIsTwoHunna :: Reply -> Bool
106respIsTwoHunna resp = NHTS.statusCode (responseStatus resp) == 200
108existentialQuery :: String -> IO (Reply, Bool)
109existentialQuery url = do
111 return (reply, respIsTwoHunna reply)
113indexExists :: Server -> IndexName -> IO Bool
114indexExists (Server server) (IndexName indexName) = do
115 (_, exists) <- existentialQuery url
117 where url = joinPath [server, indexName]
119refreshIndex :: Server -> IndexName -> IO Reply
120refreshIndex (Server server) (IndexName indexName) =
122 where url = joinPath [server, indexName, "_refresh"]
124stringifyOCIndex :: OpenCloseIndex -> String
125stringifyOCIndex oci = case oci of
127 CloseIndex -> "_close"
129openOrCloseIndexes :: OpenCloseIndex -> Server -> IndexName -> IO Reply
130openOrCloseIndexes oci (Server server) (IndexName indexName) =
132 where ociString = stringifyOCIndex oci
133 url = joinPath [server, indexName, ociString]
135openIndex :: Server -> IndexName -> IO Reply
136openIndex = openOrCloseIndexes OpenIndex
138closeIndex :: Server -> IndexName -> IO Reply
139closeIndex = openOrCloseIndexes CloseIndex
141{-| putMapping is an HTTP PUT and has upsert semantics. Mappings are schemas
142 for documents in indexes.
144putMapping :: ToJSON a => Server -> IndexName
145 -> MappingName -> a -> IO Reply
146putMapping (Server server) (IndexName indexName) (MappingName mappingName) mapping =
148 where url = joinPath [server, indexName, mappingName, "_mapping"]
149 body = Just $ encode mapping
151deleteMapping :: Server -> IndexName -> MappingName -> IO Reply
152deleteMapping (Server server) (IndexName indexName)
153 (MappingName mappingName) =
154 delete $ joinPath [server, indexName, mappingName, "_mapping"]
156indexDocument :: ToJSON doc => Server -> IndexName -> MappingName
157 -> doc -> DocId -> IO Reply
158indexDocument (Server server) (IndexName indexName)
159 (MappingName mappingName) document (DocId docId) =
161 where url = joinPath [server, indexName, mappingName, docId]
162 body = Just (encode document)
164deleteDocument :: Server -> IndexName -> MappingName
166deleteDocument (Server server) (IndexName indexName)
167 (MappingName mappingName) (DocId docId) =
168 delete $ joinPath [server, indexName, mappingName, docId]
170bulk :: Server -> [BulkOperation] -> IO Reply
171bulk (Server server) bulkOps = post url body where
172 url = joinPath [server, "_bulk"]
173 body = Just $ collapseStream bulkOps
175collapseStream :: [BulkOperation] -> L.ByteString
176collapseStream stream = collapsed where
177 blobs = intersperse "\n" $ concat $ fmap getStreamChunk stream
178 mashedTaters = mash (mempty :: Builder) blobs
179 collapsed = toLazyByteString $ mappend mashedTaters (byteString "\n")
181mash :: Builder -> [L.ByteString] -> Builder
182mash = foldl' (\b x -> mappend b (lazyByteString x))
184mkMetadataValue :: Text -> String -> String -> String -> Value
185mkMetadataValue operation indexName mappingName docId =
187 object [ "_index" .= indexName
188 , "_type" .= mappingName
191getStreamChunk :: BulkOperation -> [L.ByteString]
192getStreamChunk (BulkIndex (IndexName indexName)
193 (MappingName mappingName)
194 (DocId docId) value) = blob where
195 metadata = mkMetadataValue "index" indexName mappingName docId
196 blob = [encode metadata, encode value]
198getStreamChunk (BulkCreate (IndexName indexName)
199 (MappingName mappingName)
200 (DocId docId) value) = blob where
201 metadata = mkMetadataValue "create" indexName mappingName docId
202 blob = [encode metadata, encode value]
204getStreamChunk (BulkDelete (IndexName indexName)
205 (MappingName mappingName)
206 (DocId docId)) = blob where
207 metadata = mkMetadataValue "delete" indexName mappingName docId
208 blob = [encode metadata]
210getStreamChunk (BulkUpdate (IndexName indexName)
211 (MappingName mappingName)
212 (DocId docId) value) = blob where
213 metadata = mkMetadataValue "update" indexName mappingName docId
214 doc = object ["doc" .= value]
215 blob = [encode metadata, encode doc]
217getDocument :: Server -> IndexName -> MappingName
219getDocument (Server server) (IndexName indexName)
220 (MappingName mappingName) (DocId docId) =
221 get $ joinPath [server, indexName, mappingName, docId]
223documentExists :: Server -> IndexName -> MappingName
225documentExists (Server server) (IndexName indexName)
226 (MappingName mappingName) (DocId docId) = do
227 (_, exists) <- existentialQuery url
229 url = joinPath [server, indexName, mappingName, docId]
231dispatchSearch :: String -> Search -> IO Reply
232dispatchSearch url search = post url (Just (encode search))
234searchAll :: Server -> Search -> IO Reply
235searchAll (Server server) = dispatchSearch url where
236 url = joinPath [server, "_search"]
238searchByIndex :: Server -> IndexName -> Search -> IO Reply
239searchByIndex (Server server) (IndexName indexName) = dispatchSearch url where
240 url = joinPath [server, indexName, "_search"]
242searchByType :: Server -> IndexName -> MappingName -> Search -> IO Reply
243searchByType (Server server) (IndexName indexName)
244 (MappingName mappingName) = dispatchSearch url where
245 url = joinPath [server, indexName, mappingName, "_search"]
247mkSearch :: Maybe Query -> Maybe Filter -> Search
248mkSearch query filter = Search query filter Nothing False 0 10
250pageSearch :: Int -> Int -> Search -> Search
251pageSearch pageFrom pageSize search = search { from = pageFrom, size = pageSize }
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list