@@ -220,7 +220,7 @@ data FieldDefinition =
220 FieldDefinition { fieldType :: FieldType } deriving (Eq, Show)
220 FieldDefinition { fieldType :: FieldType } deriving (Eq, Show)
222data MappingField =
222data MappingField =
223− MappingField { fieldName :: Text
223+ MappingField { mappingFieldName :: FieldName
224 , fieldDefinition :: FieldDefinition } deriving (Eq, Show)
224 , fieldDefinition :: FieldDefinition } deriving (Eq, Show)
226data Mapping = Mapping { typeName :: Text
226data Mapping = Mapping { typeName :: Text
@@ -308,79 +308,177 @@ searchByType (Server server) indexName mappingName search = dispatchSearch url s
308 url = joinPath [server, indexName, mappingName, "_search"]
308 url = joinPath [server, indexName, mappingName, "_search"]
310data Search = Search { queryBody :: Maybe Query
310data Search = Search { queryBody :: Maybe Query
311− , filterBody :: Maybe Filter } deriving (Eq, Show)
311+ , filterBody :: Maybe Filter
312+ , sortBody :: Maybe Sort
314+ , trackSortScores :: Bool
316+ , size :: Int} deriving (Eq, Show)
318+pageSearch :: Int -> Int -> Search -> Search
319+pageSearch from size search = search { from = from, size = size }
321+-- defaultFieldMaybeJSON :: Text -> Maybe a ->
322+maybeJson field (Just value) = [field .= toJSON value]
324+maybeJsonF field (Just value) = [field .= fmap toJSON value]
313instance ToJSON Search where
327instance ToJSON Search where
314− toJSON (Search query filters) = object [--"query" .= fmap toJSON query,
328+ toJSON (Search query filter sort trackSortScores from size) =
315− "filter" .= fmap toJSON filters]
329+ object merged where
330+ lQuery = maybeJson "query" query
331+ lFilter = maybeJson "filter" filter
332+ lSort = maybeJsonF "sort" sort
333+ merged = mconcat [[ "from" .= from
335+ , "track_scores" .= trackSortScores]
340+type Sort = [SortSpec]
342+data SortSpec = DefaultSortSpec DefaultSort
343+ | GeoDistanceSortSpec SortOrder GeoPoint deriving (Eq, Show)
345+instance ToJSON SortSpec where
346+ toJSON (DefaultSortSpec
347+ (DefaultSort (FieldName sortFieldName) sortOrder ignoreUnmapped
348+ sortMode missingSort nestedFilter)) =
349+ object [sortFieldName .= object merged] where
350+ base = ["order" .= toJSON sortOrder
351+ , "ignore_unmapped" .= ignoreUnmapped]
352+ lSortMode = maybeJson "mode" sortMode
353+ lMissingSort = maybeJson "missing" missingSort
354+ lNestedFilter = maybeJson "nested_filter" nestedFilter
355+ merged = mconcat [base, lSortMode, lMissingSort, lNestedFilter]
357+instance ToJSON SortOrder where
358+ toJSON Ascending = String "asc"
359+ toJSON Descending = String "desc"
361+instance ToJSON SortMode where
362+ toJSON SortMin = String "min"
363+ toJSON SortMax = String "max"
364+ toJSON SortSum = String "sum"
365+ toJSON SortAvg = String "avg"
367+instance ToJSON Missing where
368+ toJSON LastMissing = String "_last"
369+ toJSON FirstMissing = String "_first"
370+ toJSON (CustomMissing txt) = String txt
373+ DefaultSort { sortFieldName :: FieldName
374+ , sortOrder :: SortOrder
376+ , ignoreUnmapped :: Bool
377+ , sortMode :: Maybe SortMode
378+ , missingSort :: Maybe Missing
379+ , nestedFilter :: Maybe Filter } deriving (Eq, Show)
381+data SortOrder = Ascending
382+ | Descending deriving (Eq, Show)
384+data Missing = LastMissing
386+ | CustomMissing Text deriving (Eq, Show)
388+data SortMode = SortMin
391+ | SortAvg deriving (Eq, Show)
317−type QueryString = Text
318-- status:active
393-- status:active
319-- author:"John Smith"
394-- author:"John Smith"
320-- for book.title and book.date containing quick OR brown, book.\*:(quick brown)
395-- for book.title and book.date containing quick OR brown, book.\*:(quick brown)
321-- field title has no value or doesn't exist, _missing_:title
396-- field title has no value or doesn't exist, _missing_:title
322-- field title has any non-null value, _exists:title
397-- field title has any non-null value, _exists:title
324−data BooleanOperator = AND | OR deriving (Eq, Show)
326−type DisMax = Bool -- "use_dis_max"
399+-- type DisMax = Bool -- "use_dis_max"
327−newtype TieBreaker = TieBreaker Int deriving (Eq, Show)
400+-- newtype TieBreaker = TieBreaker Int deriving (Eq, Show)
328−data QueryField = DefaultField Text
401+-- data QueryField = DefaultField Text
329− | Fields [Text] DisMax TieBreaker deriving (Eq, Show)
402+-- | Fields [Text] DisMax TieBreaker deriving (Eq, Show)
331−-- this is will go away later
404+-- -- this is will go away later
332−type Query = QueryStringQuery
405+
334−data QueryStringQuery =
406+-- data QueryStringQuery =
335− QueryStringQuery { query :: QueryString
407+-- QueryStringQuery { query :: Text
336− -- default _all
408+-- -- default _all
337− , field :: Maybe QueryField
409+-- , field :: Maybe QueryField
338− -- default OR
410+-- -- default OR
339− , defaultOperator :: Maybe BooleanOperator
411+-- , defaultOperator :: Maybe BooleanOperator
340− -- analyzer name
412+-- -- analyzer name
341− , analyzer :: Maybe Text
413+-- , analyzer :: Maybe Text
342− -- default true
414+-- -- default true
343− , allowLeadingWildcard :: Maybe Bool
415+-- , allowLeadingWildcard :: Maybe Bool
344− -- default true
416+-- -- default true
345− , lowercaseExpandedTerms :: Maybe Bool
417+-- , lowercaseExpandedTerms :: Maybe Bool
346− -- default true
418+-- -- default true
347− , enablePositionIncrements :: Maybe Bool
419+-- , enablePositionIncrements :: Maybe Bool
348− -- default 50
420+-- -- default 50
349− , fuzzyMaxExpansions :: Maybe Int
421+-- , fuzzyMaxExpansions :: Maybe Int
350− -- Fuzziness -- default AUTO, add type later
422+-- -- Fuzziness -- default AUTO, add type later
351− , fuzziness :: Maybe Text
423+-- , fuzziness :: Maybe Text
352− , fuzzyPrefixLength :: Maybe Int -- default 0
424+-- , fuzzyPrefixLength :: Maybe Int -- default 0
353− -- default 0, 0 means exact phrase matches
425+-- -- default 0, 0 means exact phrase matches
354− , phraseSlop :: Maybe Int
426+-- , phraseSlop :: Maybe Int
355− -- default 1.0
427+-- -- default 1.0
356− , boost :: Maybe Double
428+-- , boost :: Maybe Double
357− -- default false, true forces wildcard analysis
429+-- -- default false, true forces wildcard analysis
358− , analyzeWildcard :: Maybe Bool
430+-- , analyzeWildcard :: Maybe Bool
359− -- default false
431+-- -- default false
360− , autoGeneratePhraseQueries :: Maybe Bool
432+-- , autoGeneratePhraseQueries :: Maybe Bool
361− -- # "should" clauses in the boolean query should match
433+-- -- # "should" clauses in the boolean query should match
362− , minimumShouldMatch :: Maybe Text
434+-- , minimumShouldMatch :: Maybe Text
363− -- Text to handle weird % and other cases. Needs type
435+-- -- Text to handle weird % and other cases. Needs type
364− -- default false, true shuts off format based failures
436+-- -- default false, true shuts off format based failures
365− , lenient :: Maybe Bool
437+-- , lenient :: Maybe Bool
366− -- default ROOT, locale used for string conversions
438+-- -- default ROOT, locale used for string conversions
367− , locale :: Maybe Text
439+-- , locale :: Maybe Text
368− } deriving (Eq, Show)
440+-- } deriving (Eq, Show)
370−emptyQueryStringQuery = QueryStringQuery "" Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
442+-- emptyQueryStringQuery = QueryStringQuery "" Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
371−queryStringQuery query = emptyQueryStringQuery { query = query }
443+-- queryStringQuery query = emptyQueryStringQuery { query = query }
373−type FieldName = Text
445+-- type FieldName = Text
375type Cache = Bool -- caching on/off
447type Cache = Bool -- caching on/off
376−type CacheName = Text
378defaultCache = False
448defaultCache = False
380−type Existence = Bool
381−type NullValue = Bool
382type PrefixValue = Text
450type PrefixValue = Text
452+data BooleanOperator = And | Or deriving (Eq, Show)
454+newtype QueryString = QueryString Text deriving (Eq, Show)
455+newtype FieldName = FieldName Text deriving (Eq, Show)
456+newtype CacheName = CacheName Text deriving (Eq, Show)
457+newtype CacheKey = CacheKey Text deriving (Eq, Show)
458+newtype Existence = Existence Bool deriving (Eq, Show)
459+newtype NullValue = NullValue Bool deriving (Eq, Show)
461+-- data QueryType = BooleanQueryType
463+-- | PhrasePrefixQueryType deriving (Eq, Show)
466+data Query = TermQuery Term (Maybe Boost)
467+ | ConstantScoreFilter Filter Boost
468+ | ConstantScoreQuery Query Boost
471+instance ToJSON Query where
472+ toJSON (TermQuery (Term termField termValue) boost) =
474+ object [termField .= object merged]]
476+ base = ["value" .= termValue]
477+ boosted = case boost of
478+ (Just boostValue) -> ["boost" .= boostValue]
480+ merged = mappend base boosted
384data Filter = AndFilter [Filter] Cache
482data Filter = AndFilter [Filter] Cache
385 | OrFilter [Filter] Cache
483 | OrFilter [Filter] Cache
386 | NotFilter Filter Cache
484 | NotFilter Filter Cache
@@ -432,7 +530,7 @@ instance ToJSON Filter where
432 toJSON (IdentityFilter) =
530 toJSON (IdentityFilter) =
433 object ["match_all" .= object []]
531 object ["match_all" .= object []]
435− toJSON (ExistsFilter fieldName) =
533+ toJSON (ExistsFilter (FieldName fieldName)) =
436 object ["exists" .= object
534 object ["exists" .= object
437 ["field" .= fieldName]]
535 ["field" .= fieldName]]
@@ -443,7 +541,7 @@ instance ToJSON Filter where
443 object ["geo_bounding_box" .= toJSON bbConstraint
541 object ["geo_bounding_box" .= toJSON bbConstraint
444 , "type" .= toJSON filterType]
542 , "type" .= toJSON filterType]
446− toJSON (GeoDistanceFilter (GeoPoint geoField latLon)
544+ toJSON (GeoDistanceFilter (GeoPoint (FieldName geoField) latLon)
447 distance distanceType optimizeBbox cache) =
545 distance distanceType optimizeBbox cache) =
448 object ["geo_distance" .=
546 object ["geo_distance" .=
449 object ["distance" .= toJSON distance
547 object ["distance" .= toJSON distance
@@ -452,14 +550,14 @@ instance ToJSON Filter where
452 , geoField .= toJSON latLon
550 , geoField .= toJSON latLon
453 , "_cache" .= cache]]
551 , "_cache" .= cache]]
455− toJSON (GeoDistanceRangeFilter (GeoPoint geoField latLon)
553+ toJSON (GeoDistanceRangeFilter (GeoPoint (FieldName geoField) latLon)
456 (DistanceRange distanceFrom distanceTo)) =
554 (DistanceRange distanceFrom distanceTo)) =
457 object ["geo_distance_range" .=
555 object ["geo_distance_range" .=
458 object ["from" .= toJSON distanceFrom
556 object ["from" .= toJSON distanceFrom
459 , "to" .= toJSON distanceTo
557 , "to" .= toJSON distanceTo
460 , geoField .= toJSON latLon]]
558 , geoField .= toJSON latLon]]
462− toJSON (GeoPolygonFilter geoField latLons) =
560+ toJSON (GeoPolygonFilter (FieldName geoField) latLons) =
463 object ["geo_polygon" .=
561 object ["geo_polygon" .=
464 object [geoField .=
562 object [geoField .=
465 object ["points" .= fmap toJSON latLons]]]
563 object ["points" .= fmap toJSON latLons]]]
@@ -472,18 +570,18 @@ instance ToJSON Filter where
472 toJSON (LimitFilter limit) =
570 toJSON (LimitFilter limit) =
473 object ["limit" .= object ["value" .= limit]]
571 object ["limit" .= object ["value" .= limit]]
475− toJSON (MissingFilter fieldName existence nullValue) =
573+ toJSON (MissingFilter (FieldName fieldName) (Existence existence) (NullValue nullValue)) =
476 object ["missing" .=
574 object ["missing" .=
477 object ["field" .= fieldName
575 object ["field" .= fieldName
478 , "existence" .= existence
576 , "existence" .= existence
479 , "null_value" .= nullValue]]
577 , "null_value" .= nullValue]]
481− toJSON (PrefixFilter fieldName fieldValue cache) =
579+ toJSON (PrefixFilter (FieldName fieldName) fieldValue cache) =
482 object ["prefix" .=
580 object ["prefix" .=
483 object [fieldName .= fieldValue
581 object [fieldName .= fieldValue
484 , "_cache" .= cache]]
582 , "_cache" .= cache]]
486− toJSON (RangeFilter fieldName (Left halfRange) rangeExecution cache) =
584+ toJSON (RangeFilter (FieldName fieldName) (Left halfRange) rangeExecution cache) =
487 object ["range" .=
585 object ["range" .=
488 object [fieldName .=
586 object [fieldName .=
489 object [key .= val]
587 object [key .= val]
@@ -492,7 +590,7 @@ instance ToJSON Filter where
493 (key, val) = halfRangeToKV halfRange
591 (key, val) = halfRangeToKV halfRange
495− toJSON (RangeFilter fieldName (Right range) rangeExecution cache) =
593+ toJSON (RangeFilter (FieldName fieldName) (Right range) rangeExecution cache) =
496 object ["range" .=
594 object ["range" .=
497 object [fieldName .=
595 object [fieldName .=
498 object [lessKey .= lessVal
596 object [lessKey .= lessVal
@@ -502,7 +600,8 @@ instance ToJSON Filter where
503 (lessKey, lessVal, greaterKey, greaterVal) = rangeToKV range
601 (lessKey, lessVal, greaterKey, greaterVal) = rangeToKV range
603+ toJSON (RegexpFilter (FieldName fieldName)
505− toJSON (RegexpFilter fieldName (Regexp regexText) flags cacheName cache cacheKey) =
604+ (Regexp regexText) flags (CacheName cacheName) cache (CacheKey cacheKey)) =
506 object ["regexp" .=
605 object ["regexp" .=
507 object [fieldName .=
606 object [fieldName .=
508 object ["value" .= regexText
607 object ["value" .= regexText
@@ -512,7 +611,7 @@ instance ToJSON Filter where
512 , "_cache_key" .= cacheKey]]
611 , "_cache_key" .= cacheKey]]
514instance ToJSON GeoPoint where
613instance ToJSON GeoPoint where
515− toJSON (GeoPoint geoField latLon) =
614+ toJSON (GeoPoint (FieldName geoField) latLon) =
516 object [geoField .= toJSON latLon]
615 object [geoField .= toJSON latLon]
518showText :: Show a => a -> Text
617showText :: Show a => a -> Text
@@ -546,7 +645,7 @@ instance ToJSON OptimizeBbox where
546 toJSON (OptimizeGeoFilterType gft) = toJSON gft
645 toJSON (OptimizeGeoFilterType gft) = toJSON gft
548instance ToJSON GeoBoundingBoxConstraint where
647instance ToJSON GeoBoundingBoxConstraint where
549− toJSON (GeoBoundingBoxConstraint geoBBField constraintBox cache) =
648+ toJSON (GeoBoundingBoxConstraint (FieldName geoBBField) constraintBox cache) =
550 object [geoBBField .= toJSON constraintBox
649 object [geoBBField .= toJSON constraintBox
551 , "_cache" .= cache]
650 , "_cache" .= cache]
@@ -721,16 +820,16 @@ data ShardResult =
722instance (FromJSON a, ToJSON a) => FromJSON (SearchResult a) where
821instance (FromJSON a, ToJSON a) => FromJSON (SearchResult a) where
723 parseJSON (Object v) = SearchResult <$>
822 parseJSON (Object v) = SearchResult <$>
724− v .: "took" <*>
823+ v .: "took" <*>
725 v .: "timed_out" <*>
824 v .: "timed_out" <*>
726− v .: "_shards" <*>
825+ v .: "_shards" <*>
727 v .: "hits"
826 v .: "hits"
728 parseJSON _ = empty
827 parseJSON _ = empty
730instance (FromJSON a, ToJSON a) => FromJSON (SearchHits a) where
829instance (FromJSON a, ToJSON a) => FromJSON (SearchHits a) where
731 parseJSON (Object v) = SearchHits <$>
830 parseJSON (Object v) = SearchHits <$>
732− v .: "total" <*>
831+ v .: "total" <*>
733− v .: "max_score" <*>
832+ v .: "max_score" <*>
734 v .: "hits"
833 v .: "hits"
735 parseJSON _ = empty
834 parseJSON _ = empty
@@ -738,7 +837,7 @@ instance (FromJSON a, ToJSON a) => FromJSON (Hit a) where
738 parseJSON (Object v) = Hit <$>
837 parseJSON (Object v) = Hit <$>
739 v .: "_index" <*>
838 v .: "_index" <*>
740 v .: "_type" <*>
839 v .: "_type" <*>
741− v .: "_id" <*>
840+ v .: "_id" <*>
742 v .: "_score" <*>
841 v .: "_score" <*>
743 v .: "_source"
842 v .: "_source"
744 parseJSON _ = empty
843 parseJSON _ = empty