git.iko.soy/typeable/bloodhound
on master help sign in
Merged with master
6832d1eLiam Atkinson
.travis.yml+6−5
@@ -7,11 +7,12 @@
7# release of a major GHC version. Setting HPVER implictly sets
7# release of a major GHC version. Setting HPVER implictly sets
8# GHCVER. Omit lines with versions you don't need/want testing for.
8# GHCVER. Omit lines with versions you don't need/want testing for.
9env:
9env:
10− - GHCVER=7.6.3 ESVER=1.3.2
10+ - GHCVER=7.6.3 ESVER=1.4.0
11− - GHCVER=7.8.2 ESVER=1.0.3
11+ - GHCVER=7.8.3 ESVER=1.0.3
12− - GHCVER=7.8.2 ESVER=1.1.2
12+ - GHCVER=7.8.3 ESVER=1.1.2
13− - GHCVER=7.8.2 ESVER=1.2.3
13+ - GHCVER=7.8.3 ESVER=1.2.3
14− - GHCVER=7.8.2 ESVER=1.3.2
14+ - GHCVER=7.8.3 ESVER=1.3.2
15+ - GHCVER=7.8.3 ESVER=1.4.0
15
16
16# services:
17# services:
17# - elasticsearch
18# - elasticsearch
Database/Bloodhound/Client.hs+34−31
@@ -22,15 +22,18 @@ module Database.Bloodhound.Client
22 , mkShardCount
22 , mkShardCount
23 , mkReplicaCount
23 , mkReplicaCount
24 , getStatus
24 , getStatus
25+ , encodeBulkOperations
26+ , encodeBulkOperation
25 )
27 )
26 where
28 where
27
29
28import Data.Aeson
30import Data.Aeson
29import Data.ByteString.Builder
31import Data.ByteString.Builder
30import qualified Data.ByteString.Lazy.Char8 as L
32import qualified Data.ByteString.Lazy.Char8 as L
31−import Data.List (foldl', intercalate, intersperse)
33+import Data.List (intercalate)
32import Data.Maybe (fromMaybe)
34import Data.Maybe (fromMaybe)
33import Data.Text (Text)
35import Data.Text (Text)
36+import qualified Data.Vector as V
34import Network.HTTP.Client
37import Network.HTTP.Client
35import qualified Network.HTTP.Types.Method as NHTM
38import qualified Network.HTTP.Types.Method as NHTM
36import qualified Network.HTTP.Types.Status as NHTS
39import qualified Network.HTTP.Types.Status as NHTS
@@ -168,52 +171,53 @@ deleteDocument (Server server) (IndexName indexName)
168 (MappingName mappingName) (DocId docId) =
171 (MappingName mappingName) (DocId docId) =
169 delete $ joinPath [server, indexName, mappingName, docId]
172 delete $ joinPath [server, indexName, mappingName, docId]
170
173
171−bulk :: Server -> [BulkOperation] -> IO Reply
174+bulk :: Server -> V.Vector BulkOperation -> IO Reply
172bulk (Server server) bulkOps = post url body where
175bulk (Server server) bulkOps = post url body where
173 url = joinPath [server, "_bulk"]
176 url = joinPath [server, "_bulk"]
174− body = Just $ collapseStream bulkOps
177+ body = Just $ encodeBulkOperations bulkOps
175
178
176−collapseStream :: [BulkOperation] -> L.ByteString
179+encodeBulkOperations :: V.Vector BulkOperation -> L.ByteString
177−collapseStream stream = collapsed where
180+encodeBulkOperations stream = collapsed where
178− blobs = intersperse "\n" $ concat $ fmap getStreamChunk stream
181+ blobs = fmap encodeBulkOperation stream
179 mashedTaters = mash (mempty :: Builder) blobs
182 mashedTaters = mash (mempty :: Builder) blobs
180 collapsed = toLazyByteString $ mappend mashedTaters (byteString "\n")
183 collapsed = toLazyByteString $ mappend mashedTaters (byteString "\n")
181
184
182−mash :: Builder -> [L.ByteString] -> Builder
185+mash :: Builder -> V.Vector L.ByteString -> Builder
183−mash = foldl' (\b x -> mappend b (lazyByteString x))
186+mash = V.foldl' (\b x -> b `mappend` "\n" `mappend` (lazyByteString x))
184
187
185−mkMetadataValue :: Text -> String -> String -> String -> Value
188+mkBulkStreamValue :: Text -> String -> String -> String -> Value
186−mkMetadataValue operation indexName mappingName docId =
189+mkBulkStreamValue operation indexName mappingName docId =
187 object [operation .=
190 object [operation .=
188 object [ "_index" .= indexName
191 object [ "_index" .= indexName
189 , "_type" .= mappingName
192 , "_type" .= mappingName
190 , "_id" .= docId]]
193 , "_id" .= docId]]
191
194
192−getStreamChunk :: BulkOperation -> [L.ByteString]
195+encodeBulkOperation :: BulkOperation -> L.ByteString
193−getStreamChunk (BulkIndex (IndexName indexName)
196+encodeBulkOperation (BulkIndex (IndexName indexName)
194 (MappingName mappingName)
197 (MappingName mappingName)
195− (DocId docId) value) = blob where
198+ (DocId docId) value) = blob
196− metadata = mkMetadataValue "index" indexName mappingName docId
199+ where metadata = mkBulkStreamValue "index" indexName mappingName docId
197− blob = [encode metadata, encode value]
200+ blob = encode metadata `mappend` "\n" `mappend` encode value
198
201
199−getStreamChunk (BulkCreate (IndexName indexName)
202+encodeBulkOperation (BulkCreate (IndexName indexName)
200 (MappingName mappingName)
203 (MappingName mappingName)
201− (DocId docId) value) = blob where
204+ (DocId docId) value) = blob
202− metadata = mkMetadataValue "create" indexName mappingName docId
205+ where metadata = mkBulkStreamValue "create" indexName mappingName docId
203− blob = [encode metadata, encode value]
206+ blob = encode metadata `mappend` "\n" `mappend` encode value
204
207
205−getStreamChunk (BulkDelete (IndexName indexName)
208+encodeBulkOperation (BulkDelete (IndexName indexName)
206 (MappingName mappingName)
209 (MappingName mappingName)
207− (DocId docId)) = blob where
210+ (DocId docId)) = blob
208− metadata = mkMetadataValue "delete" indexName mappingName docId
211+ where metadata = mkBulkStreamValue "delete" indexName mappingName docId
209− blob = [encode metadata]
212+ blob = encode metadata
210
213
211−getStreamChunk (BulkUpdate (IndexName indexName)
214+encodeBulkOperation (BulkUpdate (IndexName indexName)
212 (MappingName mappingName)
215 (MappingName mappingName)
213− (DocId docId) value) = blob where
216+ (DocId docId) value) = blob
214− metadata = mkMetadataValue "update" indexName mappingName docId
217+ where metadata = mkBulkStreamValue "update" indexName mappingName docId
215− doc = object ["doc" .= value]
218+ doc = object ["doc" .= value]
216− blob = [encode metadata, encode doc]
219+ blob = encode metadata `mappend` "\n" `mappend` encode doc
220+
217
221
218getDocument :: Server -> IndexName -> MappingName
222getDocument :: Server -> IndexName -> MappingName
219 -> DocId -> IO Reply
223 -> DocId -> IO Reply
@@ -246,11 +250,10 @@ searchByType (Server server) (IndexName indexName)
246 url = joinPath [server, indexName, mappingName, "_search"]
250 url = joinPath [server, indexName, mappingName, "_search"]
247
251
248mkSearch :: Maybe Query -> Maybe Filter -> Search
252mkSearch :: Maybe Query -> Maybe Filter -> Search
249−mkSearch query filter = Search query filter Nothing Nothing Nothing False 0 10
253+mkSearch query filter = Search query filter Nothing Nothing Nothing False 0 0
250
254
251mkAggregateSearch :: Maybe Query -> Aggregations -> Search
255mkAggregateSearch :: Maybe Query -> Aggregations -> Search
252−mkAggregateSearch query aggregations = Search query Nothing Nothing (Just aggregations) Nothing False 0 0
256+mkAggregateSearch query mkSearchAggs = Search query Nothing Nothing (Just mkSearchAggs) Nothing False 0 0
253−
254
257
255mkHighlightSearch :: Maybe Query -> Highlights -> Search
258mkHighlightSearch :: Maybe Query -> Highlights -> Search
256mkHighlightSearch query searchHighlights = Search query Nothing Nothing Nothing (Just searchHighlights) False 0 10
259mkHighlightSearch query searchHighlights = Search query Nothing Nothing Nothing (Just searchHighlights) False 0 10
Database/Bloodhound/Types.hs+18−16
@@ -1,4 +1,5 @@
1{-# LANGUAGE DeriveGeneric #-}
1{-# LANGUAGE DeriveGeneric #-}
2+
2{-# LANGUAGE RecordWildCards #-}
3{-# LANGUAGE RecordWildCards #-}
3
4
4{-| Data types for describing actions and data structures performed to interact
5{-| Data types for describing actions and data structures performed to interact
@@ -175,14 +176,13 @@ module Database.Bloodhound.Types
175 , HighlightTag(..)
176 , HighlightTag(..)
176 , HitHighlight
177 , HitHighlight
177
178
178− , TermsResult
179+ , TermsResult(..)
179− , DateHistogramResult
180+ , DateHistogramResult(..)
180 ) where
181 ) where
181
182
182import Control.Applicative
183import Control.Applicative
183import Data.Aeson
184import Data.Aeson
184−import Data.Aeson.Types (Pair (..), emptyObject,
185+import Data.Aeson.Types (Pair, emptyObject, parseMaybe)
185− parseMaybe)
186import qualified Data.ByteString.Lazy.Char8 as L
186import qualified Data.ByteString.Lazy.Char8 as L
187import Data.List (nub)
187import Data.List (nub)
188import Data.List.NonEmpty (NonEmpty (..))
188import Data.List.NonEmpty (NonEmpty (..))
@@ -1061,7 +1061,7 @@ data ExecutionHint = Ordinals
1061 | GlobalOrdinals
1061 | GlobalOrdinals
1062 | GlobalOrdinalsHash
1062 | GlobalOrdinalsHash
1063 | GlobalOrdinalsLowCardinality
1063 | GlobalOrdinalsLowCardinality
1064− | Map deriving(Eq, Show)
1064+ | Map deriving (Eq, Show)
1065
1065
1066data TimeInterval = Weeks
1066data TimeInterval = Weeks
1067 | Days
1067 | Days
@@ -1153,7 +1153,7 @@ instance Show TimeInterval where
1153 show Seconds = "s"
1153 show Seconds = "s"
1154
1154
1155instance ToJSON Aggregation where
1155instance ToJSON Aggregation where
1156− toJSON (TermsAgg (TermsAggregation term include exclude order minDocCount size shardSize collectMode executionHint aggs)) =
1156+ toJSON (TermsAgg (TermsAggregation term include exclude order minDocCount size shardSize collectMode executionHint termAggs)) =
1157 omitNulls ["terms" .= omitNulls [ toJSON' term,
1157 omitNulls ["terms" .= omitNulls [ toJSON' term,
1158 "include" .= toJSON include,
1158 "include" .= toJSON include,
1159 "exclude" .= toJSON exclude,
1159 "exclude" .= toJSON exclude,
@@ -1164,11 +1164,11 @@ instance ToJSON Aggregation where
1164 "collect_mode" .= toJSON collectMode,
1164 "collect_mode" .= toJSON collectMode,
1165 "execution_hint" .= toJSON executionHint
1165 "execution_hint" .= toJSON executionHint
1166 ],
1166 ],
1167− "aggs" .= toJSON aggs ]
1167+ "aggs" .= toJSON termAggs ]
1168 where
1168 where
1169 toJSON' x = case x of { Left y -> "field" .= toJSON y; Right y -> "script" .= toJSON y }
1169 toJSON' x = case x of { Left y -> "field" .= toJSON y; Right y -> "script" .= toJSON y }
1170
1170
1171− toJSON (DateHistogramAgg (DateHistogramAggregation field interval format preZone postZone preOffset postOffset aggs)) =
1171+ toJSON (DateHistogramAgg (DateHistogramAggregation field interval format preZone postZone preOffset postOffset dateHistoAggs)) =
1172 omitNulls ["date_histogram" .= omitNulls [ "field" .= toJSON field,
1172 omitNulls ["date_histogram" .= omitNulls [ "field" .= toJSON field,
1173 "interval" .= toJSON interval,
1173 "interval" .= toJSON interval,
1174 "format" .= toJSON format,
1174 "format" .= toJSON format,
@@ -1177,7 +1177,7 @@ instance ToJSON Aggregation where
1177 "pre_offset" .= toJSON preOffset,
1177 "pre_offset" .= toJSON preOffset,
1178 "post_offset" .= toJSON postOffset
1178 "post_offset" .= toJSON postOffset
1179 ],
1179 ],
1180− "aggs" .= toJSON aggs ]
1180+ "aggs" .= toJSON dateHistoAggs ]
1181
1181
1182type AggregationResults = M.Map Text Value
1182type AggregationResults = M.Map Text Value
1183
1183
@@ -1226,6 +1226,7 @@ instance FromJSON TermsResult where
1226 v .: "key" <*>
1226 v .: "key" <*>
1227 v .: "doc_count" <*>
1227 v .: "doc_count" <*>
1228 v .:? "aggregations"
1228 v .:? "aggregations"
1229+ parseJSON _ = mempty
1229
1230
1230instance FromJSON DateHistogramResult where
1231instance FromJSON DateHistogramResult where
1231 parseJSON (Object v) = DateHistogramResult <$>
1232 parseJSON (Object v) = DateHistogramResult <$>
@@ -1233,6 +1234,7 @@ instance FromJSON DateHistogramResult where
1233 v .:? "key_as_string" <*>
1234 v .:? "key_as_string" <*>
1234 v .: "doc_count" <*>
1235 v .: "doc_count" <*>
1235 v .:? "aggregations"
1236 v .:? "aggregations"
1237+ parseJSON _ = mempty
1236
1238
1237instance Monoid Filter where
1239instance Monoid Filter where
1238 mempty = IdentityFilter
1240 mempty = IdentityFilter
@@ -1317,11 +1319,11 @@ instance ToJSON Filter where
1317 toJSON (RangeFilter (FieldName fieldName) (Left halfRange) rangeExecution cache) =
1319 toJSON (RangeFilter (FieldName fieldName) (Left halfRange) rangeExecution cache) =
1318 object ["range" .=
1320 object ["range" .=
1319 object [fieldName .=
1321 object [fieldName .=
1320− object [key .= val]
1322+ object [rqFKey .= rqFVal]
1321 , "execution" .= toJSON rangeExecution
1323 , "execution" .= toJSON rangeExecution
1322 , "_cache" .= cache]]
1324 , "_cache" .= cache]]
1323 where
1325 where
1324− (key, val) = halfRangeToKV halfRange
1326+ (rqFKey, rqFVal) = halfRangeToKV halfRange
1325
1327
1326 toJSON (RangeFilter (FieldName fieldName) (Right range) rangeExecution cache) =
1328 toJSON (RangeFilter (FieldName fieldName) (Right range) rangeExecution cache) =
1327 object ["range" .=
1329 object ["range" .=
@@ -1535,8 +1537,8 @@ instance ToJSON RangeQuery where
1535 toJSON (RangeQuery (FieldName fieldName) (Left halfRange) boost) =
1537 toJSON (RangeQuery (FieldName fieldName) (Left halfRange) boost) =
1536 object [ fieldName .= conjoined ]
1538 object [ fieldName .= conjoined ]
1537 where conjoined = [ "boost" .= toJSON boost
1539 where conjoined = [ "boost" .= toJSON boost
1538− , key .= val ]
1540+ , rqKey .= rqVal ]
1539− (key, val) = halfRangeToKV halfRange
1541+ (rqKey, rqVal) = halfRangeToKV halfRange
1540
1542
1541
1543
1542instance ToJSON PrefixQuery where
1544instance ToJSON PrefixQuery where
@@ -1827,16 +1829,17 @@ instance (FromJSON a) => FromJSON (EsResult a) where
1827
1829
1828
1830
1829instance ToJSON Search where
1831instance ToJSON Search where
1830− toJSON (Search query sFilter sort aggs highlight sTrackSortScores sFrom sSize) =
1832+ toJSON (Search query sFilter sort searchAggs highlight sTrackSortScores sFrom sSize) =
1831 omitNulls [ "query" .= query
1833 omitNulls [ "query" .= query
1832 , "filter" .= sFilter
1834 , "filter" .= sFilter
1833 , "sort" .= sort
1835 , "sort" .= sort
1834− , "aggregations" .= aggs
1836+ , "aggregations" .= searchAggs
1835 , "highlight" .= highlight
1837 , "highlight" .= highlight
1836 , "from" .= sFrom
1838 , "from" .= sFrom
1837 , "size" .= sSize
1839 , "size" .= sSize
1838 , "track_scores" .= sTrackSortScores]
1840 , "track_scores" .= sTrackSortScores]
1839
1841
1842+
1840instance ToJSON FieldHighlight where
1843instance ToJSON FieldHighlight where
1841 toJSON (FieldHighlight (FieldName fName) (Just fSettings)) =
1844 toJSON (FieldHighlight (FieldName fName) (Just fSettings)) =
1842 object [ fName .= fSettings ]
1845 object [ fName .= fSettings ]
@@ -1918,7 +1921,6 @@ highlightTagToPairs (Just (CustomTags (pre, post))) = [ "pre_tags" .= pre
1918 , "post_tags" .= post]
1921 , "post_tags" .= post]
1919highlightTagToPairs Nothing = []
1922highlightTagToPairs Nothing = []
1920
1923
1921−
1922instance ToJSON SortSpec where
1924instance ToJSON SortSpec where
1923 toJSON (DefaultSortSpec
1925 toJSON (DefaultSortSpec
1924 (DefaultSort (FieldName dsSortFieldName) dsSortOrder dsIgnoreUnmapped
1926 (DefaultSort (FieldName dsSortFieldName) dsSortOrder dsIgnoreUnmapped
LICENSE+8−17
@@ -1,21 +1,12 @@
1−The MIT License (MIT)
1+Copyright (c) 2014, Chris Allen
2+All rights reserved.
2
3
3−Copyright (c) <2014> <Chris Allen>
4+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
5
5−Permission is hereby granted, free of charge, to any person obtaining a copy
6+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6−of this software and associated documentation files (the "Software"), to deal
7−in the Software without restriction, including without limitation the rights
8−to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9−copies of the Software, and to permit persons to whom the Software is
10−furnished to do so, subject to the following conditions:
11
7
12−The above copyright notice and this permission notice shall be included in
8+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
13−all copies or substantial portions of the Software.
14
9
15−THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
16−IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11+
17−FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
12+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
18−AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19−LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20−OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21−THE SOFTWARE.
README.org+42−1
@@ -7,6 +7,9 @@
7#+CAPTION: Build Status
7#+CAPTION: Build Status
8[[https://travis-ci.org/bitemyapp/bloodhound][https://travis-ci.org/bitemyapp/bloodhound.svg]]
8[[https://travis-ci.org/bitemyapp/bloodhound][https://travis-ci.org/bitemyapp/bloodhound.svg]]
9
9
10+#+CAPTION: Hackage version
11+[[https://budueba.com/hackage/bloodhound]]
12+
10* Elasticsearch client and query DSL for Haskell
13* Elasticsearch client and query DSL for Haskell
11
14
12** Why?
15** Why?
@@ -17,6 +20,8 @@ Search doesn't have to be hard. Let the dog do it.
17
20
18"Bloodhound makes Elasticsearch almost tolerable!" - Almost-gruntled user
21"Bloodhound makes Elasticsearch almost tolerable!" - Almost-gruntled user
19
22
23+"ES is a nightmare but Bloodhound at least makes it tolerable." - Same user, later opinion.
24+
20** Version compatibility
25** Version compatibility
21
26
22Elasticsearch >= 1.0 is recommended. Bloodhound mostly works with 0.9.x, but I don't recommend it if you expect everything to work. As of Bloodhound 0.3 all >=1.0 versions of Elasticsearch work.
27Elasticsearch >= 1.0 is recommended. Bloodhound mostly works with 0.9.x, but I don't recommend it if you expect everything to work. As of Bloodhound 0.3 all >=1.0 versions of Elasticsearch work.
@@ -45,6 +50,7 @@ http://hackage.haskell.org/package/bloodhound
45-- the multi-line examples into your ghci REPL.
50-- the multi-line examples into your ghci REPL.
46
51
47:set -XDeriveGeneric
52:set -XDeriveGeneric
53+:{
48import Database.Bloodhound
54import Database.Bloodhound
49import Data.Aeson
55import Data.Aeson
50import Data.Either (Either(..))
56import Data.Either (Either(..))
@@ -68,6 +74,7 @@ let defaultIndexSettings = IndexSettings (ShardCount 3) (ReplicaCount 2)
68
74
69-- response :: Reply, Reply is a synonym for Network.HTTP.Conduit.Response
75-- response :: Reply, Reply is a synonym for Network.HTTP.Conduit.Response
70response <- createIndex testServer defaultIndexSettings testIndex
76response <- createIndex testServer defaultIndexSettings testIndex
77+:}
71
78
72#+END_SRC
79#+END_SRC
73
80
@@ -281,7 +288,7 @@ Right (Tweet {user = "bitemyapp"
281
288
282*** Bulk create, index
289*** Bulk create, index
283
290
284−#+BEGIN_SRC haskell
291+#+BEGIN_SRC haskell
285
292
286-- don't forget the imports and derive generic setting for ghci
293-- don't forget the imports and derive generic setting for ghci
287-- at the beginning of the examples.
294-- at the beginning of the examples.
@@ -318,6 +325,40 @@ resp <- bulk testServer stream
318
325
319#+END_SRC
326#+END_SRC
320
327
328+*** Encoding individual bulk API operations
329+
330+#+BEGIN_SRC haskell
331+-- the following functions are exported in Bloodhound so
332+-- you can build up bulk operations yourself
333+encodeBulkOperations :: V.Vector BulkOperation -> L.ByteString
334+encodeBulkOperation :: BulkOperation -> L.ByteString
335+
336+-- How to use the above:
337+data BulkTest = BulkTest { name :: Text } deriving (Eq, Generic, Show)
338+instance FromJSON BulkTest
339+instance ToJSON BulkTest
340+
341+_ <- insertData
342+let firstTest = BulkTest "blah"
343+let secondTest = BulkTest "bloo"
344+let firstDoc = BulkIndex testIndex
345+ testMapping (DocId "2") (toJSON firstTest)
346+let secondDoc = BulkCreate testIndex
347+ testMapping (DocId "3") (toJSON secondTest)
348+let stream = V.fromList [firstDoc, secondDoc] :: V.Vector BulkOperation
349+
350+-- to encode yourself
351+let firstDocEncoded = encode firstDoc :: L.ByteString
352+
353+-- to encode a vector of bulk operations
354+let encodedOperations = encodeBulkOperations stream
355+
356+-- to insert into a particular server
357+-- bulk :: Server -> V.Vector BulkOperation -> IO Reply
358+_ <- bulk testServer stream
359+
360+#+END_SRC
361+
321** Search
362** Search
322
363
323*** Querying
364*** Querying
bloodhound.cabal+1−1
@@ -3,7 +3,7 @@ version: 0.4.0.0
3synopsis: ElasticSearch client library for Haskell
3synopsis: ElasticSearch client library for Haskell
4description: ElasticSearch made awesome for Haskell hackers
4description: ElasticSearch made awesome for Haskell hackers
5homepage: https://github.com/bitemyapp/bloodhound
5homepage: https://github.com/bitemyapp/bloodhound
6−license: MIT
6+license: BSD3
7license-file: LICENSE
7license-file: LICENSE
8author: Chris Allen
8author: Chris Allen
9maintainer: cma@bitemyapp.com
9maintainer: cma@bitemyapp.com
tests/tests.hs+5−4
@@ -6,7 +6,6 @@ module Main where
6import Control.Applicative
6import Control.Applicative
7import Control.Monad
7import Control.Monad
8import Data.Aeson
8import Data.Aeson
9−import Data.Aeson.Types (parseMaybe)
10import Data.HashMap.Strict (fromList)
9import Data.HashMap.Strict (fromList)
11import Data.List (nub)
10import Data.List (nub)
12import Data.List.NonEmpty (NonEmpty (..))
11import Data.List.NonEmpty (NonEmpty (..))
@@ -60,10 +59,12 @@ es10 :: ServerVersion
60es10 = ServerVersion 1 0 0
59es10 = ServerVersion 1 0 0
61
60
62serverBranch :: ServerVersion -> ServerVersion
61serverBranch :: ServerVersion -> ServerVersion
63−serverBranch (ServerVersion maj min patch) = ServerVersion maj min 0
62+serverBranch (ServerVersion majorVer minorVer patchVer) =
63+ ServerVersion majorVer minorVer patchVer
64
64
65mkServerVersion :: [Int] -> Maybe ServerVersion
65mkServerVersion :: [Int] -> Maybe ServerVersion
66−mkServerVersion [maj, min, patch] = Just (ServerVersion maj min patch)
66+mkServerVersion [majorVer, minorVer, patchVer] =
67+ Just (ServerVersion majorVer minorVer patchVer)
67mkServerVersion _ = Nothing
68mkServerVersion _ = Nothing
68
69
69getServerVersion :: Server -> IO (Maybe ServerVersion)
70getServerVersion :: Server -> IO (Maybe ServerVersion)
@@ -246,7 +247,7 @@ main = hspec $ do
246 testMapping (DocId "2") (toJSON firstTest)
247 testMapping (DocId "2") (toJSON firstTest)
247 let secondDoc = BulkCreate testIndex
248 let secondDoc = BulkCreate testIndex
248 testMapping (DocId "3") (toJSON secondTest)
249 testMapping (DocId "3") (toJSON secondTest)
249− let stream = [firstDoc, secondDoc]
250+ let stream = V.fromList [firstDoc, secondDoc]
250 _ <- bulk testServer stream
251 _ <- bulk testServer stream
251 _ <- refreshIndex testServer testIndex
252 _ <- refreshIndex testServer testIndex
252 fDoc <- getDocument testServer testIndex testMapping (DocId "2")
253 fDoc <- getDocument testServer testIndex testMapping (DocId "2")