@@ -1,47 +1,53 @@
1−* Bloodhound
1+Bloodhound
3−#+CAPTION: Bloodhound (dog)
4−[[./bloodhound.jpg]]
4+
6+[<https://travis-ci.org/bitemyapp/bloodhound.svg>](https://travis-ci.org/bitemyapp/bloodhound)
7−#+CAPTION: Build Status
8+[<https://img.shields.io/hackage/v/bloodhound.svg?style=flat>](https://hackage.haskell.org/package/bloodhound/)
8−[[https://travis-ci.org/bitemyapp/bloodhound][https://travis-ci.org/bitemyapp/bloodhound.svg]]
10−[[https://img.shields.io/hackage/v/bloodhound.svg?style=flat]]
10+Elasticsearch client and query DSL for Haskell
11+==============================================
12−* Elasticsearch client and query DSL for Haskell
16Search doesn't have to be hard. Let the dog do it.
16Search doesn't have to be hard. Let the dog do it.
18−** Endorsements
18+Endorsements
20"Bloodhound makes Elasticsearch almost tolerable!" - Almost-gruntled user
21"Bloodhound makes Elasticsearch almost tolerable!" - Almost-gruntled user
22"ES is a nightmare but Bloodhound at least makes it tolerable." - Same user, later opinion.
23"ES is a nightmare but Bloodhound at least makes it tolerable." - Same user, later opinion.
24−** Version compatibility
25+Version compatibility
26−Elasticsearch >= 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.
28+Elasticsearch \>= 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.
28−Current versions we test against are 1.0.3, 1.1.2, 1.2.3, 1.3.2, and 1.4.0. We also check that GHC 7.6 and 7.8 both build and pass tests. See our [[https://travis-ci.org/bitemyapp/bloodhound][TravisCI]] to learn more.
30+Current versions we test against are 1.0.3, 1.1.2, 1.2.3, 1.3.2, and 1.4.0. We also check that GHC 7.6 and 7.8 both build and pass tests. See our [TravisCI](https://travis-ci.org/bitemyapp/bloodhound) to learn more.
30−** Stability
32+Stability
32Bloodhound is stable for production use. I will strive to avoid breaking API compatibility from here on forward, but dramatic features like a type-safe, fully integrated mapping API may require breaking things in the future.
35Bloodhound is stable for production use. I will strive to avoid breaking API compatibility from here on forward, but dramatic features like a type-safe, fully integrated mapping API may require breaking things in the future.
34−* Hackage page and Haddock documentation
37+Hackage page and Haddock documentation
38+======================================
36−http://hackage.haskell.org/package/bloodhound
40+<http://hackage.haskell.org/package/bloodhound>
40−** Index Operations
45+Index Operations
42−*** Create Index
48+### Create Index
44−#+BEGIN_SRC haskell
50+``` {.haskell}
46-- Formatted for use in ghci, so there are "let"s in front of the decls.
52-- Formatted for use in ghci, so there are "let"s in front of the decls.
@@ -75,22 +81,22 @@ let defaultIndexSettings = IndexSettings (ShardCount 3) (ReplicaCount 2)
75response <- createIndex testServer defaultIndexSettings testIndex
81response <- createIndex testServer defaultIndexSettings testIndex
80−*** Delete Index
86+### Delete Index
84−#+BEGIN_SRC haskell
90+``` {.haskell}
86-- response :: Reply
92-- response :: Reply
87response <- deleteIndex testServer testIndex
93response <- deleteIndex testServer testIndex
91−**** Example Response
97+#### Example Response
93−#+BEGIN_SRC haskell
99+``` {.haskell}
95-- print response if it was a success
101-- print response if it was a success
96Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}
102Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}
@@ -110,21 +116,21 @@ Response {responseStatus = Status {statusCode = 404, statusMessage = "Not Found"
110 , responseCookieJar = CJ {expose = []}
116 , responseCookieJar = CJ {expose = []}
111 , responseClose' = ResponseClose}
117 , responseClose' = ResponseClose}
115−*** Refresh Index
121+### Refresh Index
117−**** Note, you *have* to do this if you expect to read what you just wrote
123+#### Note, you **have** to do this if you expect to read what you just wrote
119−#+BEGIN_SRC haskell
125+``` {.haskell}
121resp <- refreshIndex testServer testIndex
127resp <- refreshIndex testServer testIndex
125−**** Example Response
131+#### Example Response
127−#+BEGIN_SRC haskell
133+``` {.haskell}
129-- print resp on success
135-- print resp on success
130Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}
136Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}
@@ -135,13 +141,14 @@ Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}
135 , responseCookieJar = CJ {expose = []}
141 , responseCookieJar = CJ {expose = []}
136 , responseClose' = ResponseClose}
142 , responseClose' = ResponseClose}
140−** Mapping Operations
146+Mapping Operations
142−*** Create Mapping
149+### Create Mapping
144−#+BEGIN_SRC haskell
151+``` {.haskell}
146-- don't forget imports and the like at the top.
153-- don't forget imports and the like at the top.
@@ -162,21 +169,22 @@ instance ToJSON TweetMapping where
163resp <- putMapping testServer testIndex testMapping TweetMapping
170resp <- putMapping testServer testIndex testMapping TweetMapping
167−*** Delete Mapping
174+### Delete Mapping
169−#+BEGIN_SRC haskell
176+``` {.haskell}
171resp <- deleteMapping testServer testIndex testMapping
178resp <- deleteMapping testServer testIndex testMapping
175−** Document Operations
182+Document Operations
177−*** Indexing Documents
185+### Indexing Documents
179−#+BEGIN_SRC haskell
187+``` {.haskell}
181-- don't forget the imports and derive generic setting for ghci
189-- don't forget the imports and derive generic setting for ghci
182-- at the beginning of the examples.
190-- at the beginning of the examples.
@@ -214,11 +222,11 @@ instance FromJSON Location
215resp <- indexDocument testServer testIndex testMapping exampleTweet (DocId "1")
223resp <- indexDocument testServer testIndex testMapping exampleTweet (DocId "1")
219−**** Example Response
227+#### Example Response
221−#+BEGIN_SRC haskell
229+``` {.haskell}
223Response {responseStatus =
231Response {responseStatus =
224 Status {statusCode = 200, statusMessage = "OK"}
232 Status {statusCode = 200, statusMessage = "OK"}
@@ -228,19 +236,19 @@ Response {responseStatus =
228 , responseBody = "{\"_index\":\"twitter\",\"_type\":\"tweet\",\"_id\":\"1\",\"_version\":2,\"created\":false}"
236 , responseBody = "{\"_index\":\"twitter\",\"_type\":\"tweet\",\"_id\":\"1\",\"_version\":2,\"created\":false}"
229 , responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose}
237 , responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose}
233−*** Deleting Documents
241+### Deleting Documents
235−#+BEGIN_SRC haskell
243+``` {.haskell}
237resp <- deleteDocument testServer testIndex testMapping (DocId "1")
245resp <- deleteDocument testServer testIndex testMapping (DocId "1")
241−*** Getting Documents
249+### Getting Documents
243−#+BEGIN_SRC haskell
251+``` {.haskell}
245-- n.b., you'll need the earlier imports. responseBody is from http-conduit
253-- n.b., you'll need the earlier imports. responseBody is from http-conduit
@@ -281,13 +289,14 @@ Right (Tweet {user = "bitemyapp"
281 , age = 10000
289 , age = 10000
282 , location = Location {lat = 40.12, lon = -71.34}})
290 , location = Location {lat = 40.12, lon = -71.34}})
286−** Bulk Operations
294+Bulk Operations
288−*** Bulk create, index
297+### Bulk create, index
290−#+BEGIN_SRC haskell
299+``` {.haskell}
292-- don't forget the imports and derive generic setting for ghci
301-- don't forget the imports and derive generic setting for ghci
293-- at the beginning of the examples.
302-- at the beginning of the examples.
@@ -322,11 +331,11 @@ let stream = [firstDoc, secondDoc]
322resp <- bulk testServer stream
331resp <- bulk testServer stream
327−*** Encoding individual bulk API operations
336+### Encoding individual bulk API operations
329−#+BEGIN_SRC haskell
338+``` {.haskell}
330-- the following functions are exported in Bloodhound so
339-- the following functions are exported in Bloodhound so
331-- you can build up bulk operations yourself
340-- you can build up bulk operations yourself
332encodeBulkOperations :: V.Vector BulkOperation -> L.ByteString
341encodeBulkOperations :: V.Vector BulkOperation -> L.ByteString
@@ -356,15 +365,16 @@ let encodedOperations = encodeBulkOperations stream
356-- bulk :: Server -> V.Vector BulkOperation -> IO Reply
365-- bulk :: Server -> V.Vector BulkOperation -> IO Reply
357_ <- bulk testServer stream
366_ <- bulk testServer stream
363−*** Querying
373+### Querying
365−**** Term Query
375+#### Term Query
367−#+BEGIN_SRC haskell
377+``` {.haskell}
369-- exported by the Client module, just defaults some stuff.
379-- exported by the Client module, just defaults some stuff.
370-- mkSearch :: Maybe Query -> Maybe Filter -> Search
380-- mkSearch :: Maybe Query -> Maybe Filter -> Search
@@ -397,31 +407,30 @@ Right [Hit {hitIndex = IndexName "twitter"
397 , age = 10000
407 , age = 10000
398 , location = Location {lat = 40.12, lon = -71.34}}}]
408 , location = Location {lat = 40.12, lon = -71.34}}}]
402−**** Match Query
412+#### Match Query
404−#+BEGIN_SRC haskell
414+``` {.haskell}
406let query = QueryMatchQuery $ mkMatchQuery (FieldName "user") (QueryString "bitemyapp")
416let query = QueryMatchQuery $ mkMatchQuery (FieldName "user") (QueryString "bitemyapp")
407let search = mkSearch (Just query) Nothing
417let search = mkSearch (Just query) Nothing
412−**** Multi-Match Query
421+#### Multi-Match Query
414−#+BEGIN_SRC haskell
423+``` {.haskell}
416let fields = [FieldName "user", FieldName "message"]
425let fields = [FieldName "user", FieldName "message"]
417let query = QueryMultiMatchQuery $ mkMultiMatchQuery fields (QueryString "bitemyapp")
426let query = QueryMultiMatchQuery $ mkMultiMatchQuery fields (QueryString "bitemyapp")
418let search = mkSearch (Just query) Nothing
427let search = mkSearch (Just query) Nothing
422−**** Bool Query
431+#### Bool Query
424−#+BEGIN_SRC haskell
433+``` {.haskell}
426let innerQuery = QueryMatchQuery $
435let innerQuery = QueryMatchQuery $
427 mkMatchQuery (FieldName "user") (QueryString "bitemyapp")
436 mkMatchQuery (FieldName "user") (QueryString "bitemyapp")
@@ -429,11 +438,11 @@ let query = QueryBoolQuery $
429 mkBoolQuery [innerQuery] [] []
438 mkBoolQuery [innerQuery] [] []
430let search = mkSearch (Just query) Nothing
439let search = mkSearch (Just query) Nothing
434−**** Boosting Query
443+#### Boosting Query
436−#+BEGIN_SRC haskell
445+``` {.haskell}
438let posQuery = QueryMatchQuery $
447let posQuery = QueryMatchQuery $
439 mkMatchQuery (FieldName "user") (QueryString "bitemyapp")
448 mkMatchQuery (FieldName "user") (QueryString "bitemyapp")
@@ -442,15 +451,15 @@ let negQuery = QueryMatchQuery $
442let query = QueryBoostingQuery $
451let query = QueryBoostingQuery $
443 BoostingQuery posQuery negQuery (Boost 0.2)
452 BoostingQuery posQuery negQuery (Boost 0.2)
447−**** Rest of the query/filter types
456+#### Rest of the query/filter types
449Just follow the pattern you've seen here and check the Hackage API documentation.
458Just follow the pattern you've seen here and check the Hackage API documentation.
451−*** Sorting
460+### Sorting
453−#+BEGIN_SRC haskell
462+``` {.haskell}
455let sortSpec = DefaultSortSpec $ mkSort (FieldName "age") Ascending
464let sortSpec = DefaultSortSpec $ mkSort (FieldName "age") Ascending
@@ -476,15 +485,15 @@ let sortSpec = DefaultSortSpec $ mkSort (FieldName "age") Ascending
476-- just add more sortspecs to the list if you want tie-breakers.
485-- just add more sortspecs to the list if you want tie-breakers.
477let search = Search Nothing (Just IdentityFilter) (Just [sortSpec]) False 0 10
486let search = Search Nothing (Just IdentityFilter) (Just [sortSpec]) False 0 10
481−*** Filtering
490+### Filtering
483−**** And, Not, and Or filters
492+#### And, Not, and Or filters
485Filters form a monoid and seminearring.
494Filters form a monoid and seminearring.
487−#+BEGIN_SRC haskell
496+``` {.haskell}
489instance Monoid Filter where
498instance Monoid Filter where
490 mempty = IdentityFilter
499 mempty = IdentityFilter
@@ -513,11 +522,11 @@ IdentityFilter <||> someOtherFilter
514NotFilter someOtherFilter False
523NotFilter someOtherFilter False
518−**** Identity Filter
527+#### Identity Filter
520−#+BEGIN_SRC haskell
529+``` {.haskell}
522-- And'ing two Identity
531-- And'ing two Identity
523let queryFilter = IdentityFilter <&&> IdentityFilter
532let queryFilter = IdentityFilter <&&> IdentityFilter
@@ -526,13 +535,13 @@ let search = mkSearch Nothing (Just queryFilter)
527reply <- searchByType testServer testIndex testMapping search
536reply <- searchByType testServer testIndex testMapping search
531−**** Boolean Filter
540+#### Boolean Filter
533Similar to boolean queries.
542Similar to boolean queries.
535−#+BEGIN_SRC haskell
544+``` {.haskell}
537-- Will return only items whose "user" field contains the term "bitemyapp"
546-- Will return only items whose "user" field contains the term "bitemyapp"
538let queryFilter = BoolFilter (MustMatch (Term "user" "bitemyapp") False)
547let queryFilter = BoolFilter (MustMatch (Term "user" "bitemyapp") False)
@@ -546,31 +555,31 @@ let queryFilter = BoolFilter (MustNotMatch (Term "user" "bitemyapp") False)
546-- clauses to match can be set using the minimum_should_match parameter.
555-- clauses to match can be set using the minimum_should_match parameter.
547let queryFilter = BoolFilter (ShouldMatch [(Term "user" "bitemyapp")] False)
556let queryFilter = BoolFilter (ShouldMatch [(Term "user" "bitemyapp")] False)
551−**** Exists Filter
560+#### Exists Filter
553−#+BEGIN_SRC haskell
562+``` {.haskell}
555-- Will filter for documents that have the field "user"
564-- Will filter for documents that have the field "user"
556let existsFilter = ExistsFilter (FieldName "user")
565let existsFilter = ExistsFilter (FieldName "user")
560−**** Geo BoundingBox Filter
569+#### Geo BoundingBox Filter
562−#+BEGIN_SRC haskell
571+``` {.haskell}
564-- topLeft and bottomRight
573-- topLeft and bottomRight
565let box = GeoBoundingBox (LatLon 40.73 (-74.1)) (LatLon 40.10 (-71.12))
574let box = GeoBoundingBox (LatLon 40.73 (-74.1)) (LatLon 40.10 (-71.12))
567let constraint = GeoBoundingBoxConstraint (FieldName "tweet.location") box False GeoFilterMemory
576let constraint = GeoBoundingBoxConstraint (FieldName "tweet.location") box False GeoFilterMemory
571−**** Geo Distance Filter
580+#### Geo Distance Filter
573−#+BEGIN_SRC haskell
582+``` {.haskell}
575let geoPoint = GeoPoint (FieldName "tweet.location") (LatLon 40.12 (-71.34))
584let geoPoint = GeoPoint (FieldName "tweet.location") (LatLon 40.12 (-71.34))
@@ -585,13 +594,13 @@ let optimizeBbox = OptimizeGeoFilterType GeoFilterMemory
586let geoFilter = GeoDistanceFilter geoPoint distance SloppyArc optimizeBbox False
595let geoFilter = GeoDistanceFilter geoPoint distance SloppyArc optimizeBbox False
590−**** Geo Distance Range Filter
599+#### Geo Distance Range Filter
592Think of a donut and you won't be far off.
601Think of a donut and you won't be far off.
594−#+BEGIN_SRC haskell
603+``` {.haskell}
596let geoPoint = GeoPoint (FieldName "tweet.location") (LatLon 40.12 (-71.34))
605let geoPoint = GeoPoint (FieldName "tweet.location") (LatLon 40.12 (-71.34))
@@ -599,11 +608,11 @@ let distanceRange = DistanceRange (Distance 0.0 Miles) (Distance 10.0 Miles)
600let geoFilter = GeoDistanceRangeFilter geoPoint distanceRange
609let geoFilter = GeoDistanceRangeFilter geoPoint distanceRange
604−**** Geo Polygon Filter
613+#### Geo Polygon Filter
606−#+BEGIN_SRC haskell
615+``` {.haskell}
608-- I think I drew a square here.
617-- I think I drew a square here.
609let points = [LatLon 40.0 (-70.00),
618let points = [LatLon 40.0 (-70.00),
@@ -613,22 +622,22 @@ let points = [LatLon 40.0 (-70.00),
614let geoFilter = GeoPolygonFilter (FieldName "tweet.location") points
623let geoFilter = GeoPolygonFilter (FieldName "tweet.location") points
618−**** Document IDs filter
627+#### Document IDs filter
620−#+BEGIN_SRC haskell
629+``` {.haskell}
622-- takes a mapping name and a list of DocIds
631-- takes a mapping name and a list of DocIds
623IdsFilter (MappingName "tweet") [DocId "1"]
632IdsFilter (MappingName "tweet") [DocId "1"]
627−**** Range Filter
636+#### Range Filter
629−***** Full Range
638+##### Full Range
631−#+BEGIN_SRC haskell
640+``` {.haskell}
633-- RangeFilter :: FieldName
642-- RangeFilter :: FieldName
634-- -> Either HalfRange Range
643-- -> Either HalfRange Range
@@ -639,21 +648,21 @@ let filter = RangeFilter (FieldName "age")
639 (Right (RangeLtGt (LessThan 100000.0) (GreaterThan 1000.0)))
648 (Right (RangeLtGt (LessThan 100000.0) (GreaterThan 1000.0)))
640 RangeExecutionIndex False
649 RangeExecutionIndex False
644−***** Half Range
653+##### Half Range
646−#+BEGIN_SRC haskell
655+``` {.haskell}
648let filter = RangeFilter (FieldName "age")
657let filter = RangeFilter (FieldName "age")
649 (Left (HalfRangeLt (LessThan 100000.0)))
658 (Left (HalfRangeLt (LessThan 100000.0)))
650 RangeExecutionIndex False
659 RangeExecutionIndex False
654−**** Regexp Filter
663+#### Regexp Filter
656−#+BEGIN_SRC haskell
665+``` {.haskell}
658-- RegexpFilter
667-- RegexpFilter
659-- :: FieldName
668-- :: FieldName
@@ -678,47 +687,48 @@ let filter = RegexpFilter (FieldName "user") (Regexp "bite.*app")
678-- | Intersection
687-- | Intersection
679-- | Interval deriving (Eq, Show)
688-- | Interval deriving (Eq, Show)
694+#### Adding aggregations to search
684−**** Adding aggregations to search
685Aggregations can now be added to search queries, or made on their own.
696Aggregations can now be added to search queries, or made on their own.
686−#+BEGIN_SRC haskell
698+``` {.haskell}
687type Aggregations = M.Map Text Aggregation
699type Aggregations = M.Map Text Aggregation
688data Aggregation
700data Aggregation
689 = TermsAgg TermsAggregation
701 = TermsAgg TermsAggregation
690 | DateHistogramAgg DateHistogramAggregation
702 | DateHistogramAgg DateHistogramAggregation
693−For convenience, ```mkAggregations``` exists, that will create an
705+For convenience, \`\`\`mkAggregations\`\`\` exists, that will create an \`\`\`Aggregations\`\`\` with the aggregation provided.
694−```Aggregations``` with the aggregation provided.
696For example:
707For example:
697−#+BEGIN_SRC haskell
709+``` {.haskell}
698 let a = mkAggregations "users" $ TermsAgg $ mkTermsAggregation "user"
710 let a = mkAggregations "users" $ TermsAgg $ mkTermsAggregation "user"
699 let search = mkAggregateSearch Nothing a
711 let search = mkAggregateSearch Nothing a
702−Aggregations can be added to an existing search, using the
714+Aggregations can be added to an existing search, using the \`\`\`aggBody\`\`\` field
705−#+BEGIN_SRC haskell
716+``` {.haskell}
706 let search = mkSearch (Just (MatchAllQuery Nothing)) Nothing
717 let search = mkSearch (Just (MatchAllQuery Nothing)) Nothing
707 let search' = search {aggBody = Just a}
718 let search' = search {aggBody = Just a}
710−Since the ```Aggregations``` structure is just a Map Text
711−Aggregation, M.insert can be used to add additional aggregations.
721+Since the \`\`\`Aggregations\`\`\` structure is just a Map Text Aggregation, M.insert can be used to add additional aggregations.
713−#+BEGIN_SRC haskell
723+``` {.haskell}
714 let a' = M.insert "age" (TermsAgg $ mkTermsAggregation "age") a
724 let a' = M.insert "age" (TermsAgg $ mkTermsAggregation "age") a
717−**** Extracting aggregations from results
727+#### Extracting aggregations from results
718−Aggregations are part of the reply structure of every search, in the
719−form of ~Maybe AggregationResults~
729+Aggregations are part of the reply structure of every search, in the form of
721−#+BEGIN_SRC haskell
731+``` {.haskell}
722-- Lift decode and response body to be in the IO monad.
732-- Lift decode and response body to be in the IO monad.
723let decode' = liftM decode
733let decode' = liftM decode
724let responseBody' = liftM responseBody
734let responseBody' = liftM responseBody
@@ -730,25 +740,24 @@ let response = decode' $ responseBody' reply :: IO (Maybe (SearchResult Tweet))
730let terms = do { response' <- response; return $ response' >>= aggregations >>= toTerms "users" }
740let terms = do { response' <- response; return $ response' >>= aggregations >>= toTerms "users" }
732Just (Bucket {buckets = [TermsResult {termKey = "bitemyapp", termsDocCount = 1, termsAggs = Nothing}]})
742Just (Bucket {buckets = [TermsResult {termKey = "bitemyapp", termsDocCount = 1, termsAggs = Nothing}]})
735−Note that bucket aggregation results, such as the TermsResult is a
745+Note that bucket aggregation results, such as the TermsResult is a member of the type class :
736−member of the type class ~BucketAggregation~:
738−#+BEGIN_SRC haskell
747+``` {.haskell}
739class BucketAggregation a where
748class BucketAggregation a where
740 key :: a -> Text
749 key :: a -> Text
741 docCount :: a -> Int
750 docCount :: a -> Int
742 aggs :: a -> Maybe AggregationResults
751 aggs :: a -> Maybe AggregationResults
743−#+END_SRC haskell
754+haskell
756+You can use the function to get any nested results, if there were any. For example, if there were a nested terms aggregation keyed to "age" in a TermsResult named , you would call
745−You can use the ~aggs~ function to get any nested results, if
758+#### Terms Aggregation
746−there were any. For example, if there were a nested terms
747−aggregation keyed to "age" in a TermsResult named ~termresult~, you would call ~aggs termresult >>=
750−**** Terms Aggregation
751−#+BEGIN_SRC haskell
760+``` {.haskell}
752data TermsAggregation
761data TermsAggregation
753 = TermsAggregation {term :: Either Text Text,
762 = TermsAggregation {term :: Either Text Text,
754 termInclude :: Maybe TermInclusion,
763 termInclude :: Maybe TermInclusion,
@@ -760,30 +769,27 @@ data TermsAggregation
760 termCollectMode :: Maybe CollectionMode,
769 termCollectMode :: Maybe CollectionMode,
761 termExecutionHint :: Maybe ExecutionHint,
770 termExecutionHint :: Maybe ExecutionHint,
762 termAggs :: Maybe Aggregations}
771 termAggs :: Maybe Aggregations}
765−Term Aggregations have two factory functions,
774+Term Aggregations have two factory functions, , and , and can be used as follows:
766−~mkTermsAggregation~, and ~mkTermsScriptAggregation~, and can
769−#+BEGIN_SRC haskell
776+``` {.haskell}
770let ta = TermsAgg $ mkTermsAggregation "user"
777let ta = TermsAgg $ mkTermsAggregation "user"
773−There are of course other options that can be added to a Terms
780+There are of course other options that can be added to a Terms Aggregation, such as the collection mode:
774−Aggregation, such as the collection mode:
781+
775−#+BEGIN_SRC haskell
782+``` {.haskell}
776let ta = mkTermsAggregation "user"
783let ta = mkTermsAggregation "user"
777let ta' = ta { termCollectMode = Just BreadthFirst }
784let ta' = ta { termCollectMode = Just BreadthFirst }
778let ta'' = TermsAgg ta'
785let ta'' = TermsAgg ta'
781−For more documentation on how the Terms Aggregation works, see
782−http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html
788+For more documentation on how the Terms Aggregation works, see <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html>
784−**** Date Histogram Aggregation
790+#### Date Histogram Aggregation
786−#+BEGIN_SRC haskell
792+``` {.haskell}
787data DateHistogramAggregation
793data DateHistogramAggregation
788 = DateHistogramAggregation {dateField :: FieldName,
794 = DateHistogramAggregation {dateField :: FieldName,
789 dateInterval :: Interval,
795 dateInterval :: Interval,
@@ -793,116 +799,132 @@ data DateHistogramAggregation
793 datePreOffset :: Maybe Text,
799 datePreOffset :: Maybe Text,
794 datePostOffset :: Maybe Text,
800 datePostOffset :: Maybe Text,
795 dateAggs :: Maybe Aggregations}
801 dateAggs :: Maybe Aggregations}
796−#+END_SRC haskell
804+haskell
798−The Date Histogram Aggregation works much the same as the Terms
806+The Date Histogram Aggregation works much the same as the Terms Aggregation.
801−Relevant functions include ~mkDateHistogram~, and ~toDateHistogram~
808+Relevant functions include , and
803−#+BEGIN_SRC haskell
810+``` {.haskell}
804let dh = DateHistogramAgg (mkDateHistogram (FieldName "postDate") Minute)
811let dh = DateHistogramAgg (mkDateHistogram (FieldName "postDate") Minute)
807−Date histograms also accept a ~FractionalInterval~:
814+Date histograms also accept a :
809−#+BEGIN_SRC haskell
816+``` {.haskell}
810FractionalInterval :: Float -> TimeInterval -> Interval
817FractionalInterval :: Float -> TimeInterval -> Interval
811-- TimeInterval is the following:
818-- TimeInterval is the following:
812data TimeInterval = Weeks | Days | Hours | Minutes | Seconds
819data TimeInterval = Weeks | Days | Hours | Minutes | Seconds
815It can be used as follows:
822It can be used as follows:
817−#+BEGIN_SRC haskell
824+``` {.haskell}
818let dh = DateHistogramAgg (mkDateHistogram (FieldName "postDate") (FractionalInterval 1.5 Minutes))
825let dh = DateHistogramAgg (mkDateHistogram (FieldName "postDate") (FractionalInterval 1.5 Minutes))
821−The ~DateHistogramResult~ is defined as:
828+The is defined as:
823−#+BEGIN_SRC haskell
830+``` {.haskell}
824data DateHistogramResult
831data DateHistogramResult
825 = DateHistogramResult {dateKey :: Int,
832 = DateHistogramResult {dateKey :: Int,
826 dateKeyStr :: Maybe Text,
833 dateKeyStr :: Maybe Text,
827 dateDocCount :: Int,
834 dateDocCount :: Int,
828 dateHistogramAggs :: Maybe AggregationResults}
835 dateHistogramAggs :: Maybe AggregationResults}
831−It is an instance of ~BucketAggregation~, and can have nested
838+It is an instance of , and can have nested aggregations in each bucket.
832−aggregations in each bucket.
834−Buckets can be extracted from a ~AggregationResult~ using
840+Buckets can be extracted from a using
835−~toDateHistogram name~
837−For more information on the Date Histogram Aggregation, see:
838−http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-bucket-datehistogram-aggregation.html
842+For more information on the Date Histogram Aggregation, see: <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-bucket-datehistogram-aggregation.html>
840−* Possible future functionality
844+Possible future functionality
845+=============================
842−** Span Queries
847+Span Queries
844−Beginning here: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-span-first-query.html
850+Beginning here: <http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-span-first-query.html>
846−** Function Score Query
852+Function Score Query
848−http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html
855+<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html>
850−** Node discovery and failover
857+Node discovery and failover
858+---------------------------
852Might require TCP support.
860Might require TCP support.
854−** Support for TCP access to Elasticsearch
862+Support for TCP access to Elasticsearch
863+---------------------------------------
856Pretend to be a transport client?
865Pretend to be a transport client?
858−** Bulk cluster-join merge
867+Bulk cluster-join merge
868+-----------------------
860Might require making a lucene index on disk with the appropriate format.
870Might require making a lucene index on disk with the appropriate format.
862−** GeoShapeQuery
872+GeoShapeQuery
864−http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-geo-shape-query.html
875+<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-geo-shape-query.html>
866−** GeoShapeFilter
877+GeoShapeFilter
868−http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-geo-shape-filter.html
880+<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-geo-shape-filter.html>
870−** Geohash cell filter
882+Geohash cell filter
872−http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-geohash-cell-filter.html
885+<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-geohash-cell-filter.html>
874−** HasChild Filter
887+HasChild Filter
876−http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-has-child-filter.html
890+<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-has-child-filter.html>
878−** HasParent Filter
892+HasParent Filter
880−http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-has-parent-filter.html
895+<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-has-parent-filter.html>
882−** Indices Filter
897+Indices Filter
884−http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-indices-filter.html
900+<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-indices-filter.html>
886−** Query Filter
902+Query Filter
888−http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-query-filter.html
905+<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-query-filter.html>
890−** Script based sorting
907+Script based sorting
892−http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#_script_based_sorting
910+<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html#_script_based_sorting>
894−** Collapsing redundantly nested and/or structures
912+Collapsing redundantly nested and/or structures
913+-----------------------------------------------
896The Seminearring instance, if deeply nested can possibly produce nested structure that is redundant. Depending on how this affects ES perforamnce, reducing this structure might be valuable.
915The Seminearring instance, if deeply nested can possibly produce nested structure that is redundant. Depending on how this affects ES perforamnce, reducing this structure might be valuable.
898−** Runtime checking for cycles in data structures
917+Runtime checking for cycles in data structures
918+----------------------------------------------
920+check for n \> 1 occurrences in DFS:
900−check for n > 1 occurrences in DFS:
922+<http://hackage.haskell.org/package/stable-maps-0.0.5/docs/System-Mem-StableName-Dynamic.html>
902−http://hackage.haskell.org/package/stable-maps-0.0.5/docs/System-Mem-StableName-Dynamic.html
924+<http://hackage.haskell.org/package/stable-maps-0.0.5/docs/System-Mem-StableName-Dynamic-Map.html>
904−http://hackage.haskell.org/package/stable-maps-0.0.5/docs/System-Mem-StableName-Dynamic-Map.html
926+Photo Origin
906−* Photo Origin
929+Photo from HA! Designs: <https://www.flickr.com/photos/hadesigns/>
908−Photo from HA! Designs: https://www.flickr.com/photos/hadesigns/