@@ -1,47 +1,53 @@
1−* Bloodhound
1+Bloodhound
2+==========
23
3−#+CAPTION: Bloodhound (dog)
4−[[./bloodhound.jpg]]
4+
55
6+[<https://travis-ci.org/bitemyapp/bloodhound.svg>](https://travis-ci.org/bitemyapp/bloodhound)
67
7−#+CAPTION: Build Status
8−[[https://travis-ci.org/bitemyapp/bloodhound][https://travis-ci.org/bitemyapp/bloodhound.svg]]
8+[<https://img.shields.io/hackage/v/bloodhound.svg?style=flat>](https://hackage.haskell.org/package/bloodhound/)
99
10−[[https://img.shields.io/hackage/v/bloodhound.svg?style=flat]]
10+Elasticsearch client and query DSL for Haskell
11+==============================================
1112
12−* Elasticsearch client and query DSL for Haskell
13−
14−** Why?
13+Why?
14+----
1515
1616Search doesn't have to be hard. Let the dog do it.
1717
18−** Endorsements
18+Endorsements
19+------------
1920
2021"Bloodhound makes Elasticsearch almost tolerable!" - Almost-gruntled user
2122
2223"ES is a nightmare but Bloodhound at least makes it tolerable." - Same user, later opinion.
2324
24−** Version compatibility
25+Version compatibility
26+---------------------
2527
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.
2729
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.
2931
30−** Stability
32+Stability
33+---------
3134
3235Bloodhound 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.
3336
34−* Hackage page and Haddock documentation
37+Hackage page and Haddock documentation
38+======================================
3539
36−http://hackage.haskell.org/package/bloodhound
40+<http://hackage.haskell.org/package/bloodhound>
3741
38−* Examples
42+Examples
43+========
3944
40−** Index Operations
45+Index Operations
46+----------------
4147
42−*** Create Index
48+### Create Index
4349
44−#+BEGIN_SRC haskell
50+``` {.haskell}
4551
4652-- Formatted for use in ghci, so there are "let"s in front of the decls.
4753
@@ -75,22 +81,22 @@ let defaultIndexSettings = IndexSettings (ShardCount 3) (ReplicaCount 2)
7581response <- createIndex testServer defaultIndexSettings testIndex
7682:}
7783
78−#+END_SRC
84+```
7985
80−*** Delete Index
86+### Delete Index
8187
82−**** Code
88+#### Code
8389
84−#+BEGIN_SRC haskell
90+``` {.haskell}
8591
8692-- response :: Reply
8793response <- deleteIndex testServer testIndex
8894
89−#+END_SRC
95+```
9096
91−**** Example Response
97+#### Example Response
9298
93−#+BEGIN_SRC haskell
99+``` {.haskell}
94100
95101-- print response if it was a success
96102Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}
@@ -110,21 +116,21 @@ Response {responseStatus = Status {statusCode = 404, statusMessage = "Not Found"
110116 , responseCookieJar = CJ {expose = []}
111117 , responseClose' = ResponseClose}
112118
113−#+END_SRC
119+```
114120
115−*** Refresh Index
121+### Refresh Index
116122
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
118124
119−#+BEGIN_SRC haskell
125+``` {.haskell}
120126
121127resp <- refreshIndex testServer testIndex
122128
123−#+END_SRC
129+```
124130
125−**** Example Response
131+#### Example Response
126132
127−#+BEGIN_SRC haskell
133+``` {.haskell}
128134
129135-- print resp on success
130136Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}
@@ -135,13 +141,14 @@ Response {responseStatus = Status {statusCode = 200, statusMessage = "OK"}
135141 , responseCookieJar = CJ {expose = []}
136142 , responseClose' = ResponseClose}
137143
138−#+END_SRC
144+```
139145
140−** Mapping Operations
146+Mapping Operations
147+------------------
141148
142−*** Create Mapping
149+### Create Mapping
143150
144−#+BEGIN_SRC haskell
151+``` {.haskell}
145152
146153-- don't forget imports and the like at the top.
147154
@@ -162,21 +169,22 @@ instance ToJSON TweetMapping where
162169
163170resp <- putMapping testServer testIndex testMapping TweetMapping
164171
165−#+END_SRC
172+```
166173
167−*** Delete Mapping
174+### Delete Mapping
168175
169−#+BEGIN_SRC haskell
176+``` {.haskell}
170177
171178resp <- deleteMapping testServer testIndex testMapping
172179
173−#+END_SRC
180+```
174181
175−** Document Operations
182+Document Operations
183+-------------------
176184
177−*** Indexing Documents
185+### Indexing Documents
178186
179−#+BEGIN_SRC haskell
187+``` {.haskell}
180188
181189-- don't forget the imports and derive generic setting for ghci
182190-- at the beginning of the examples.
@@ -214,11 +222,11 @@ instance FromJSON Location
214222
215223resp <- indexDocument testServer testIndex testMapping exampleTweet (DocId "1")
216224
217−#+END_SRC
225+```
218226
219−**** Example Response
227+#### Example Response
220228
221−#+BEGIN_SRC haskell
229+``` {.haskell}
222230
223231Response {responseStatus =
224232 Status {statusCode = 200, statusMessage = "OK"}
@@ -228,19 +236,19 @@ Response {responseStatus =
228236 , responseBody = "{\"_index\":\"twitter\",\"_type\":\"tweet\",\"_id\":\"1\",\"_version\":2,\"created\":false}"
229237 , responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose}
230238
231−#+END_SRC
239+```
232240
233−*** Deleting Documents
241+### Deleting Documents
234242
235−#+BEGIN_SRC haskell
243+``` {.haskell}
236244
237245resp <- deleteDocument testServer testIndex testMapping (DocId "1")
238246
239−#+END_SRC
247+```
240248
241−*** Getting Documents
249+### Getting Documents
242250
243−#+BEGIN_SRC haskell
251+``` {.haskell}
244252
245253-- n.b., you'll need the earlier imports. responseBody is from http-conduit
246254
@@ -281,13 +289,14 @@ Right (Tweet {user = "bitemyapp"
281289 , age = 10000
282290 , location = Location {lat = 40.12, lon = -71.34}})
283291
284−#+END_SRC
292+```
285293
286−** Bulk Operations
294+Bulk Operations
295+---------------
287296
288−*** Bulk create, index
297+### Bulk create, index
289298
290−#+BEGIN_SRC haskell
299+``` {.haskell}
291300
292301-- don't forget the imports and derive generic setting for ghci
293302-- at the beginning of the examples.
@@ -322,11 +331,11 @@ let stream = [firstDoc, secondDoc]
322331resp <- bulk testServer stream
323332:}
324333
325−#+END_SRC
334+```
326335
327−*** Encoding individual bulk API operations
336+### Encoding individual bulk API operations
328337
329−#+BEGIN_SRC haskell
338+``` {.haskell}
330339-- the following functions are exported in Bloodhound so
331340-- you can build up bulk operations yourself
332341encodeBulkOperations :: V.Vector BulkOperation -> L.ByteString
@@ -356,15 +365,16 @@ let encodedOperations = encodeBulkOperations stream
356365-- bulk :: Server -> V.Vector BulkOperation -> IO Reply
357366_ <- bulk testServer stream
358367
359−#+END_SRC
368+```
360369
361−** Search
370+Search
371+------
362372
363−*** Querying
373+### Querying
364374
365−**** Term Query
375+#### Term Query
366376
367−#+BEGIN_SRC haskell
377+``` {.haskell}
368378
369379-- exported by the Client module, just defaults some stuff.
370380-- mkSearch :: Maybe Query -> Maybe Filter -> Search
@@ -397,31 +407,30 @@ Right [Hit {hitIndex = IndexName "twitter"
397407 , age = 10000
398408 , location = Location {lat = 40.12, lon = -71.34}}}]
399409
400−#+END_SRC
410+```
401411
402−**** Match Query
412+#### Match Query
403413
404−#+BEGIN_SRC haskell
414+``` {.haskell}
405415
406416let query = QueryMatchQuery $ mkMatchQuery (FieldName "user") (QueryString "bitemyapp")
407417let search = mkSearch (Just query) Nothing
408418
409−#+END_SRC
410−
419+```
411420
412−**** Multi-Match Query
421+#### Multi-Match Query
413422
414−#+BEGIN_SRC haskell
423+``` {.haskell}
415424
416425let fields = [FieldName "user", FieldName "message"]
417426let query = QueryMultiMatchQuery $ mkMultiMatchQuery fields (QueryString "bitemyapp")
418427let search = mkSearch (Just query) Nothing
419428
420−#+END_SRC
429+```
421430
422−**** Bool Query
431+#### Bool Query
423432
424−#+BEGIN_SRC haskell
433+``` {.haskell}
425434
426435let innerQuery = QueryMatchQuery $
427436 mkMatchQuery (FieldName "user") (QueryString "bitemyapp")
@@ -429,11 +438,11 @@ let query = QueryBoolQuery $
429438 mkBoolQuery [innerQuery] [] []
430439let search = mkSearch (Just query) Nothing
431440
432−#+END_SRC
441+```
433442
434−**** Boosting Query
443+#### Boosting Query
435444
436−#+BEGIN_SRC haskell
445+``` {.haskell}
437446
438447let posQuery = QueryMatchQuery $
439448 mkMatchQuery (FieldName "user") (QueryString "bitemyapp")
@@ -442,15 +451,15 @@ let negQuery = QueryMatchQuery $
442451let query = QueryBoostingQuery $
443452 BoostingQuery posQuery negQuery (Boost 0.2)
444453
445−#+END_SRC
454+```
446455
447−**** Rest of the query/filter types
456+#### Rest of the query/filter types
448457
449458Just follow the pattern you've seen here and check the Hackage API documentation.
450459
451−*** Sorting
460+### Sorting
452461
453−#+BEGIN_SRC haskell
462+``` {.haskell}
454463
455464let sortSpec = DefaultSortSpec $ mkSort (FieldName "age") Ascending
456465
@@ -476,15 +485,15 @@ let sortSpec = DefaultSortSpec $ mkSort (FieldName "age") Ascending
476485-- just add more sortspecs to the list if you want tie-breakers.
477486let search = Search Nothing (Just IdentityFilter) (Just [sortSpec]) False 0 10
478487
479−#+END_SRC
488+```
480489
481−*** Filtering
490+### Filtering
482491
483−**** And, Not, and Or filters
492+#### And, Not, and Or filters
484493
485494Filters form a monoid and seminearring.
486495
487−#+BEGIN_SRC haskell
496+``` {.haskell}
488497
489498instance Monoid Filter where
490499 mempty = IdentityFilter
@@ -513,11 +522,11 @@ IdentityFilter <||> someOtherFilter
513522
514523NotFilter someOtherFilter False
515524
516−#+END_SRC
525+```
517526
518−**** Identity Filter
527+#### Identity Filter
519528
520−#+BEGIN_SRC haskell
529+``` {.haskell}
521530
522531-- And'ing two Identity
523532let queryFilter = IdentityFilter <&&> IdentityFilter
@@ -526,13 +535,13 @@ let search = mkSearch Nothing (Just queryFilter)
526535
527536reply <- searchByType testServer testIndex testMapping search
528537
529−#+END_SRC
538+```
530539
531−**** Boolean Filter
540+#### Boolean Filter
532541
533542Similar to boolean queries.
534543
535−#+BEGIN_SRC haskell
544+``` {.haskell}
536545
537546-- Will return only items whose "user" field contains the term "bitemyapp"
538547let queryFilter = BoolFilter (MustMatch (Term "user" "bitemyapp") False)
@@ -546,31 +555,31 @@ let queryFilter = BoolFilter (MustNotMatch (Term "user" "bitemyapp") False)
546555-- clauses to match can be set using the minimum_should_match parameter.
547556let queryFilter = BoolFilter (ShouldMatch [(Term "user" "bitemyapp")] False)
548557
549−#+END_SRC
558+```
550559
551−**** Exists Filter
560+#### Exists Filter
552561
553−#+BEGIN_SRC haskell
562+``` {.haskell}
554563
555564-- Will filter for documents that have the field "user"
556565let existsFilter = ExistsFilter (FieldName "user")
557566
558−#+END_SRC
567+```
559568
560−**** Geo BoundingBox Filter
569+#### Geo BoundingBox Filter
561570
562−#+BEGIN_SRC haskell
571+``` {.haskell}
563572
564573-- topLeft and bottomRight
565574let box = GeoBoundingBox (LatLon 40.73 (-74.1)) (LatLon 40.10 (-71.12))
566575
567576let constraint = GeoBoundingBoxConstraint (FieldName "tweet.location") box False GeoFilterMemory
568577
569−#+END_SRC
578+```
570579
571−**** Geo Distance Filter
580+#### Geo Distance Filter
572581
573−#+BEGIN_SRC haskell
582+``` {.haskell}
574583
575584let geoPoint = GeoPoint (FieldName "tweet.location") (LatLon 40.12 (-71.34))
576585
@@ -585,13 +594,13 @@ let optimizeBbox = OptimizeGeoFilterType GeoFilterMemory
585594
586595let geoFilter = GeoDistanceFilter geoPoint distance SloppyArc optimizeBbox False
587596
588−#+END_SRC
597+```
589598
590−**** Geo Distance Range Filter
599+#### Geo Distance Range Filter
591600
592601Think of a donut and you won't be far off.
593602
594−#+BEGIN_SRC haskell
603+``` {.haskell}
595604
596605let geoPoint = GeoPoint (FieldName "tweet.location") (LatLon 40.12 (-71.34))
597606
@@ -599,11 +608,11 @@ let distanceRange = DistanceRange (Distance 0.0 Miles) (Distance 10.0 Miles)
599608
600609let geoFilter = GeoDistanceRangeFilter geoPoint distanceRange
601610
602−#+END_SRC
611+```
603612
604−**** Geo Polygon Filter
613+#### Geo Polygon Filter
605614
606−#+BEGIN_SRC haskell
615+``` {.haskell}
607616
608617-- I think I drew a square here.
609618let points = [LatLon 40.0 (-70.00),
@@ -613,22 +622,22 @@ let points = [LatLon 40.0 (-70.00),
613622
614623let geoFilter = GeoPolygonFilter (FieldName "tweet.location") points
615624
616−#+END_SRC
625+```
617626
618−**** Document IDs filter
627+#### Document IDs filter
619628
620−#+BEGIN_SRC haskell
629+``` {.haskell}
621630
622631-- takes a mapping name and a list of DocIds
623632IdsFilter (MappingName "tweet") [DocId "1"]
624633
625−#+END_SRC
634+```
626635
627−**** Range Filter
636+#### Range Filter
628637
629−***** Full Range
638+##### Full Range
630639
631−#+BEGIN_SRC haskell
640+``` {.haskell}
632641
633642-- RangeFilter :: FieldName
634643-- -> Either HalfRange Range
@@ -639,21 +648,21 @@ let filter = RangeFilter (FieldName "age")
639648 (Right (RangeLtGt (LessThan 100000.0) (GreaterThan 1000.0)))
640649 RangeExecutionIndex False
641650
642−#+END_SRC
651+```
643652
644−***** Half Range
653+##### Half Range
645654
646−#+BEGIN_SRC haskell
655+``` {.haskell}
647656
648657let filter = RangeFilter (FieldName "age")
649658 (Left (HalfRangeLt (LessThan 100000.0)))
650659 RangeExecutionIndex False
651660
652−#+END_SRC
661+```
653662
654−**** Regexp Filter
663+#### Regexp Filter
655664
656−#+BEGIN_SRC haskell
665+``` {.haskell}
657666
658667-- RegexpFilter
659668-- :: FieldName
@@ -678,47 +687,48 @@ let filter = RegexpFilter (FieldName "user") (Regexp "bite.*app")
678687-- | Intersection
679688-- | Interval deriving (Eq, Show)
680689
681−#+END_SRC
690+```
691+
692+### Aggregations
693+
694+#### Adding aggregations to search
682695
683−*** Aggregations
684−**** Adding aggregations to search
685696Aggregations can now be added to search queries, or made on their own.
686−#+BEGIN_SRC haskell
697+
698+``` {.haskell}
687699type Aggregations = M.Map Text Aggregation
688700data Aggregation
689701 = TermsAgg TermsAggregation
690702 | DateHistogramAgg DateHistogramAggregation
691−#+END_SRC
703+```
692704
693−For convenience, ```mkAggregations``` exists, that will create an
694−```Aggregations``` with the aggregation provided.
705+For convenience, \`\`\`mkAggregations\`\`\` exists, that will create an \`\`\`Aggregations\`\`\` with the aggregation provided.
695706
696707For example:
697−#+BEGIN_SRC haskell
708+
709+``` {.haskell}
698710 let a = mkAggregations "users" $ TermsAgg $ mkTermsAggregation "user"
699711 let search = mkAggregateSearch Nothing a
700−#+END_SRC
712+```
701713
702−Aggregations can be added to an existing search, using the
703−```aggBody``` field
714+Aggregations can be added to an existing search, using the \`\`\`aggBody\`\`\` field
704715
705−#+BEGIN_SRC haskell
716+``` {.haskell}
706717 let search = mkSearch (Just (MatchAllQuery Nothing)) Nothing
707718 let search' = search {aggBody = Just a}
708−#+END_SRC
719+```
709720
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.
712722
713−#+BEGIN_SRC haskell
723+``` {.haskell}
714724 let a' = M.insert "age" (TermsAgg $ mkTermsAggregation "age") a
715−#+END_SRC
725+```
716726
717−**** Extracting aggregations from results
718−Aggregations are part of the reply structure of every search, in the
719−form of ~Maybe AggregationResults~
727+#### Extracting aggregations from results
720728
721−#+BEGIN_SRC haskell
729+Aggregations are part of the reply structure of every search, in the form of
730+
731+``` {.haskell}
722732-- Lift decode and response body to be in the IO monad.
723733let decode' = liftM decode
724734let responseBody' = liftM responseBody
@@ -730,25 +740,24 @@ let response = decode' $ responseBody' reply :: IO (Maybe (SearchResult Tweet))
730740let terms = do { response' <- response; return $ response' >>= aggregations >>= toTerms "users" }
731741terms
732742Just (Bucket {buckets = [TermsResult {termKey = "bitemyapp", termsDocCount = 1, termsAggs = Nothing}]})
733−#+END_SRC
743+```
734744
735−Note that bucket aggregation results, such as the TermsResult is a
736−member of the type class ~BucketAggregation~:
745+Note that bucket aggregation results, such as the TermsResult is a member of the type class :
737746
738−#+BEGIN_SRC haskell
747+``` {.haskell}
739748class BucketAggregation a where
740749 key :: a -> Text
741750 docCount :: a -> Int
742751 aggs :: a -> Maybe AggregationResults
743−#+END_SRC haskell
752+```
753+
754+haskell
755+
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
744757
745−You can use the ~aggs~ function to get any nested results, if
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 >>=
748−toTerms "age"~
758+#### Terms Aggregation
749759
750−**** Terms Aggregation
751−#+BEGIN_SRC haskell
760+``` {.haskell}
752761data TermsAggregation
753762 = TermsAggregation {term :: Either Text Text,
754763 termInclude :: Maybe TermInclusion,
@@ -760,30 +769,27 @@ data TermsAggregation
760769 termCollectMode :: Maybe CollectionMode,
761770 termExecutionHint :: Maybe ExecutionHint,
762771 termAggs :: Maybe Aggregations}
763−#+END_SRC
772+```
764773
765−Term Aggregations have two factory functions,
766−~mkTermsAggregation~, and ~mkTermsScriptAggregation~, and can
767−be used as follows:
774+Term Aggregations have two factory functions, , and , and can be used as follows:
768775
769−#+BEGIN_SRC haskell
776+``` {.haskell}
770777let ta = TermsAgg $ mkTermsAggregation "user"
771−#+END_SRC
778+```
772779
773−There are of course other options that can be added to a Terms
774−Aggregation, such as the collection mode:
775−#+BEGIN_SRC haskell
780+There are of course other options that can be added to a Terms Aggregation, such as the collection mode:
781+
782+``` {.haskell}
776783let ta = mkTermsAggregation "user"
777784let ta' = ta { termCollectMode = Just BreadthFirst }
778785let ta'' = TermsAgg ta'
779−#+END_SRC
786+```
780787
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>
783789
784−**** Date Histogram Aggregation
790+#### Date Histogram Aggregation
785791
786−#+BEGIN_SRC haskell
792+``` {.haskell}
787793data DateHistogramAggregation
788794 = DateHistogramAggregation {dateField :: FieldName,
789795 dateInterval :: Interval,
@@ -793,116 +799,132 @@ data DateHistogramAggregation
793799 datePreOffset :: Maybe Text,
794800 datePostOffset :: Maybe Text,
795801 dateAggs :: Maybe Aggregations}
796−#+END_SRC haskell
802+```
803+
804+haskell
797805
798−The Date Histogram Aggregation works much the same as the Terms
799−Aggregation.
806+The Date Histogram Aggregation works much the same as the Terms Aggregation.
800807
801−Relevant functions include ~mkDateHistogram~, and ~toDateHistogram~
808+Relevant functions include , and
802809
803−#+BEGIN_SRC haskell
810+``` {.haskell}
804811let dh = DateHistogramAgg (mkDateHistogram (FieldName "postDate") Minute)
805−#+END_SRC
812+```
806813
807−Date histograms also accept a ~FractionalInterval~:
814+Date histograms also accept a :
808815
809−#+BEGIN_SRC haskell
816+``` {.haskell}
810817FractionalInterval :: Float -> TimeInterval -> Interval
811818-- TimeInterval is the following:
812819data TimeInterval = Weeks | Days | Hours | Minutes | Seconds
813−#+END_SRC
820+```
814821
815822It can be used as follows:
816823
817−#+BEGIN_SRC haskell
824+``` {.haskell}
818825let dh = DateHistogramAgg (mkDateHistogram (FieldName "postDate") (FractionalInterval 1.5 Minutes))
819−#+END_SRC
826+```
820827
821−The ~DateHistogramResult~ is defined as:
828+The is defined as:
822829
823−#+BEGIN_SRC haskell
830+``` {.haskell}
824831data DateHistogramResult
825832 = DateHistogramResult {dateKey :: Int,
826833 dateKeyStr :: Maybe Text,
827834 dateDocCount :: Int,
828835 dateHistogramAggs :: Maybe AggregationResults}
829−#+END_SRC
836+```
830837
831−It is an instance of ~BucketAggregation~, and can have nested
832−aggregations in each bucket.
838+It is an instance of , and can have nested aggregations in each bucket.
833839
834−Buckets can be extracted from a ~AggregationResult~ using
835−~toDateHistogram name~
840+Buckets can be extracted from a using
836841
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>
839843
840−* Possible future functionality
844+Possible future functionality
845+=============================
841846
842−** Span Queries
847+Span Queries
848+------------
843849
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>
845851
846−** Function Score Query
852+Function Score Query
853+--------------------
847854
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>
849856
850−** Node discovery and failover
857+Node discovery and failover
858+---------------------------
851859
852860Might require TCP support.
853861
854−** Support for TCP access to Elasticsearch
862+Support for TCP access to Elasticsearch
863+---------------------------------------
855864
856865Pretend to be a transport client?
857866
858−** Bulk cluster-join merge
867+Bulk cluster-join merge
868+-----------------------
859869
860870Might require making a lucene index on disk with the appropriate format.
861871
862−** GeoShapeQuery
872+GeoShapeQuery
873+-------------
863874
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>
865876
866−** GeoShapeFilter
877+GeoShapeFilter
878+--------------
867879
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>
869881
870−** Geohash cell filter
882+Geohash cell filter
883+-------------------
871884
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>
873886
874−** HasChild Filter
887+HasChild Filter
888+---------------
875889
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>
877891
878−** HasParent Filter
892+HasParent Filter
893+----------------
879894
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>
881896
882−** Indices Filter
897+Indices Filter
898+--------------
883899
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>
885901
886−** Query Filter
902+Query Filter
903+------------
887904
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>
889906
890−** Script based sorting
907+Script based sorting
908+--------------------
891909
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>
893911
894−** Collapsing redundantly nested and/or structures
912+Collapsing redundantly nested and/or structures
913+-----------------------------------------------
895914
896915The 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.
897916
898−** Runtime checking for cycles in data structures
917+Runtime checking for cycles in data structures
918+----------------------------------------------
919+
920+check for n \> 1 occurrences in DFS:
899921
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>
901923
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>
903925
904−http://hackage.haskell.org/package/stable-maps-0.0.5/docs/System-Mem-StableName-Dynamic-Map.html
926+Photo Origin
927+============
905928
906−* Photo Origin
929+Photo from HA! Designs: <https://www.flickr.com/photos/hadesigns/>
907930
908−Photo from HA! Designs: https://www.flickr.com/photos/hadesigns/