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 the Github compatibility workflow for a listing of Elasticsearch and OpenSearch versions we test against.
The workflow executions can be seen in the Github actions view.
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 Bloodhound project uses Github workflows using Cabal to test for regressions and compatibility. A convenient development environment is provided by Nix and a Makefile, though the project can be built with only Cabal.
To run the tests:
- Get into the Nix environment by running
nix develop
(ornix-shell
for a non-flake setup) - Start Elasticsearch defined by
docker-compose.yml
:make compose
- Run the tests with Cabal:
cabal test
The second step can be left out if ElasticSearch (or OpenSearch) is started manually.
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
}
-}
- Chris Allen
- Liam Atkinson
- Christopher Guiney
- Curtis Carter
- Michael Xavier
- Bob Long
- Maximilian Tagher
- Anna Kopp
- Matvey B. Aksenov
- Jan-Philip Loos
- Gautier DI FOLCO
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/