Search doesn't have to be hard. Let the dog do it.
"Bloodhound makes Elasticsearch almost tolerable!" - Almost-gruntled user
"ES is a nightmare but Bloodhound at least makes it tolerable." - Same user, later opinion.
See our TravisCI for a listing of Elasticsearch version we test against.
Bloodhound 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.
The TravisCI tests are run using Stack. You should use Stack instead of cabal
to build and test Bloodhound to avoid compatibility problems. You will also need to have an Elasticsearch instance running at localhost:9200
in order to execute some of the tests. See the "Version compatibility" section above for a list of Elasticsearch versions that are officially validated against in TravisCI.
Steps to run the tests locally:
stack setup && stack build
localhost:9200
, which should be the default.stack test
in your local Bloodhound directory.stack test
. If you want to start with a clean slate, stop your Elasticsearch instance, delete the data/
folder in the Elasticsearch installation, restart Elasticsearch, and re-run stack test
.Any contribution is welcomed, for consistency reason ormolu
is used.
http://hackage.haskell.org/package/bloodhound
It's not using Bloodhound, but if you need an introduction to or overview of Elasticsearch and how to use it, you can use this screencast.
See the examples directory for example code.
indexDocument testIndex defaultIndexDocumentSettings exampleTweet (DocId "1")
{-
IndexedDocument
{ idxDocIndex = "twitter"
, idxDocType = "_doc"
, idxDocId = "1"
, idxDocVersion = 3
, idxDocResult = "updated"
, idxDocShards =
ShardResult
{ shardTotal = 1
, shardsSuccessful = 1
, shardsSkipped = 0
, shardsFailed = 0
}
, idxDocSeqNo = 2
, idxDocPrimaryTerm = 1
}
-}
let query = TermQuery (Term "user" "bitemyapp") boost
let search = mkSearch (Just query) boost
searchByIndex @_ @Tweet testIndex search
{-
SearchResult
{ took = 1
, timedOut = False
, shards =
ShardResult
{ shardTotal = 1
, shardsSuccessful = 1
, shardsSkipped = 0
, shardsFailed = 0
}
, searchHits =
SearchHits
{ hitsTotal = HitsTotal { value = 2 , relation = HTR_EQ }
, maxScore = Just 0.18232156
, hits =
[ Hit
{ hitIndex = IndexName "twitter"
, hitDocId = DocId "1"
, hitScore = Just 0.18232156
, hitSource =
Just
Tweet
{ user = "bitemyapp"
, postDate = 2009-06-18 00:00:10 UTC
, message = "Use haskell!"
, age = 10000
, location = LatLon { lat = 40.12 , lon = -71.3 }
}
, hitSort = Nothing
, hitFields = Nothing
, hitHighlight = Nothing
, hitInnerHits = Nothing
}
, Hit
{ hitIndex = IndexName "twitter"
, hitDocId = DocId "2"
, hitScore = Just 0.18232156
, hitSource =
Just
Tweet
{ user = "bitemyapp"
, postDate = 2009-06-18 00:00:10 UTC
, message = "Use haskell!"
, age = 10000
, location = LatLon { lat = 40.12 , lon = -71.3 }
}
, hitSort = Nothing
, hitFields = Nothing
, hitHighlight = Nothing
, hitInnerHits = Nothing
}
]
}
, aggregations = Nothing
, scrollId = Nothing
, suggest = Nothing
, pitId = Nothing
}
-}
Beginning here: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-span-first-query.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html
Might require TCP support.
Pretend to be a transport client?
Might require making a lucene index on disk with the appropriate format.
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geo-shape-query.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geo-shape-filter.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geohash-cell-filter.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-has-child-filter.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-has-parent-filter.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-indices-filter.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-filter.html
The Seminearring instance, if deeply nested can possibly produce nested structure that is redundant. Depending on how this affects ES performance, reducing this structure might be valuable.
check for n > 1 occurrences in DFS:
http://hackage.haskell.org/package/stable-maps-0.0.5/docs/System-Mem-StableName-Dynamic.html
http://hackage.haskell.org/package/stable-maps-0.0.5/docs/System-Mem-StableName-Dynamic-Map.html
Photo from HA! Designs: https://www.flickr.com/photos/hadesigns/