@@ -283,6 +283,199 @@ Right [Hit {hitIndex = IndexName "twitter"
283283
284284*** Filtering
285285
286+**** And, Not, and Or filters
287+
288+Filters form a monoid and seminearring.
289+
290+#+BEGIN_SRC haskell
291+
292+instance Monoid Filter where
293+ mempty = IdentityFilter
294+ mappend a b = AndFilter [a, b] defaultCache
295+
296+instance Seminearring Filter where
297+ a <||> b = OrFilter [a, b] defaultCache
298+
299+-- AndFilter and OrFilter take [Filter] as an argument.
300+
301+-- This will return anything, because IdentityFilter returns everything
302+OrFilter [IdentityFilter, someOtherFilter] False
303+
304+-- This will return exactly what someOtherFilter returns
305+AndFilter [IdentityFilter, someOtherFilter] False
306+
307+-- Thanks to the seminearring and monoid, the above can be expressed as:
308+
309+-- "and"
310+IdentityFilter <&&> someOtherFilter
311+
312+-- "or"
313+IdentityFilter <||> someOtherFilter
314+
315+-- Also there is a NotFilter, it only accepts a single filter, not a list.
316+
317+NotFilter someOtherFilter False
318+
319+#+END_SRC
320+
321+**** Identity Filter
322+
323+#+BEGIN_SRC haskell
324+
325+-- And'ing two Identity
326+let queryFilter = IdentityFilter <&&> IdentityFilter
327+
328+let search = mkSearch Nothing (Just queryFilter)
329+
330+reply <- searchByType testServer testIndex testMapping search
331+
332+#+END_SRC
333+
334+**** Boolean Filter
335+
336+Similar to boolean queries.
337+
338+#+BEGIN_SRC haskell
339+
340+-- Will return only items whose "user" field contains the term "bitemyapp"
341+let queryFilter = BoolFilter (MustMatch (Term "user" "bitemyapp") False)
342+
343+-- Will return only items whose "user" field does not contain the term "bitemyapp"
344+let queryFilter = BoolFilter (MustNotMatch (Term "user" "bitemyapp") False)
345+
346+-- The clause (query) should appear in the matching document.
347+-- In a boolean query with no must clauses, one or more should
348+-- clauses must match a document. The minimum number of should
349+-- clauses to match can be set using the minimum_should_match parameter.
350+let queryFilter = BoolFilter (ShouldMatch [(Term "user" "bitemyapp")] False)
351+
352+#+END_SRC
353+
354+**** Exists Filter
355+
356+#+BEGIN_SRC haskell
357+
358+-- Will filter for documents that have the field "user"
359+let existsFilter = ExistsFilter (FieldName "user")
360+
361+#+END_SRC
362+
363+**** Geo BoundingBox Filter
364+
365+#+BEGIN_SRC haskell
366+
367+-- topLeft and bottomRight
368+let box = GeoBoundingBox (LatLon 40.73 (-74.1)) (LatLon 40.10 (-71.12))
369+
370+let constraint = GeoBoundingBoxConstraint (FieldName "tweet.location") box False
371+
372+-- second argument is GeoFilterType, memory or indexed.
373+let geoFilter = GeoBoundingBoxFilter constraint GeoFilterMemory
374+
375+#+END_SRC
376+
377+**** Geo Distance Filter
378+
379+#+BEGIN_SRC haskell
380+
381+let geoPoint = GeoPoint (FieldName "tweet.location") (LatLon 40.12 (-71.34))
382+
383+-- coefficient and units
384+let distance = Distance 10.0 Miles
385+
386+-- GeoFilterType or NoOptimizeBbox
387+let optimizeBbox = OptimizeGeoFilterType GeoFilterMemory
388+
389+-- SloppyArc is the usual/default optimization in Elasticsearch today
390+-- but pre-1.0 versions will need to pick Arc or Plane.
391+
392+let geoFilter = GeoDistanceFilter geoPoint distance SloppyArc optimizeBbox False
393+
394+#+END_SRC
395+
396+**** Geo Distance Range Filter
397+
398+Think of a donut and you won't be far off.
399+
400+#+BEGIN_SRC haskell
401+
402+let geoPoint = GeoPoint (FieldName "tweet.location") (LatLon 40.12 (-71.34))
403+
404+let distanceRange = DistanceRange (Distance 0.0 Miles) (Distance 10.0 Miles)
405+
406+let geoFilter = GeoDistanceRangeFilter geoPoint distanceRange
407+
408+#+END_SRC
409+
410+**** Geo Polygon Filter
411+
412+#+BEGIN_SRC haskell
413+
414+-- I think I drew a square here.
415+let points = [LatLon 40.0 (-70.00),
416+ LatLon 40.0 (-72.00),
417+ LatLon 41.0 (-70.00),
418+ LatLon 41.0 (-72.00)]
419+
420+let geoFilter = GeoPolygonFilter (FieldName "tweet.location") points
421+
422+#+END_SRC
423+
424+**** Document IDs filter
425+
426+#+BEGIN_SRC haskell
427+
428+-- takes a mapping name and a list of DocIds
429+IdsFilter (MappingName "tweet") [DocId "1"]
430+
431+#+END_SRC
432+
433+**** Range Filter
434+
435+***** Full Range
436+
437+#+BEGIN_SRC haskell
438+
439+-- RangeFilter :: FieldName
440+-- -> Either HalfRange Range
441+-- -> RangeExecution
442+-- -> Cache -> Filter
443+
444+let filter = RangeFilter (FieldName "age")
445+ (Right (RangeLtGt (LessThan 100000.0) (GreaterThan 1000.0)))
446+ RangeExecutionIndex False
447+
448+#+END_SRC
449+
450+***** Half Range
451+
452+#+BEGIN_SRC haskell
453+
454+let filter = RangeFilter (FieldName "age")
455+ (Left (HalfRangeLt (LessThan 100000.0)))
456+ RangeExecutionIndex False
457+
458+#+END_SRC
459+
460+***** Regexp Filter
461+
462+#+BEGIN_SRC haskell
463+
464+-- RegexpFilter
465+-- :: FieldName
466+-- -> Regexp
467+-- -> RegexpFlags
468+-- -> CacheName
469+-- -> Cache
470+-- -> CacheKey
471+-- -> Filter
472+let filter = RegexpFilter (FieldName "user") (Regexp "bite.*app")
473+ RegexpAll (CacheName "test") False (CacheKey "key")
474+
475+-- RegexpFlags can be a combination of RegexpAll, Complement,
476+-- Interval, Intersection, AnyString, and a combination of two options thereof.
477+
478+#+END_SRC
286479
287480* Possible future functionality
288481