packages feed

bloodhound-1.0.0.0: README.md

Bloodhound 
![compatbuild](https://github.com/bitemyapp/bloodhound/actions/workflows/compat.yml/badge.svg)
[![Haskell](https://github.com/bitemyapp/bloodhound/actions/workflows/haskell.yml/badge.svg)](https://github.com/bitemyapp/bloodhound/actions/workflows/haskell.yml)
![nix](https://github.com/bitemyapp/bloodhound/actions/workflows/nix.yml/badge.svg)
![ormolu](https://github.com/bitemyapp/bloodhound/actions/workflows/ormolu.yml/badge.svg)
[![Hackage](https://img.shields.io/hackage/v/bloodhound.svg?style=flat)](https://hackage.haskell.org/package/bloodhound)
==========

![Bloodhound (dog)](./bloodhound.jpg)

Elasticsearch and OpenSearch client and query DSL for Haskell
=============================================================

Why?
----

Search doesn't have to be hard. Let the dog do it.

Endorsements
------------

"Bloodhound makes Elasticsearch almost tolerable!" - Almost-gruntled user

"ES is a nightmare but Bloodhound at least makes it tolerable." - Same user, later opinion.

Version compatibility
---------------------

Bloodhound supports and is continuously tested against the following
Elasticsearch and OpenSearch releases (see the
[compat workflow](./.github/workflows/compat.yml) and the
[CI runs](https://github.com/bitemyapp/bloodhound/actions/workflows/compat.yml)):

| Backend       | CI-tested version |
|---------------|-------------------|
| Elasticsearch | 7.17.25           |
| Elasticsearch | 8.19.16           |
| Elasticsearch | 9.4.2             |
| OpenSearch    | 1.3.19            |
| OpenSearch    | 2.19.5            |
| OpenSearch    | 3.7.0             |

Backends
--------

Each backend is exposed as its own type-safe module set, so only the
endpoints that actually exist on that version are available:

* `Database.Bloodhound.ElasticSearch7.*`
* `Database.Bloodhound.ElasticSearch8.*`
* `Database.Bloodhound.ElasticSearch9.*`
* `Database.Bloodhound.OpenSearch1.*`
* `Database.Bloodhound.OpenSearch2.*`
* `Database.Bloodhound.OpenSearch3.*`

A shared `Database.Bloodhound.Common.*` layer carries the cross-backend
surface, and `Database.Bloodhound.Dynamic.*` dispatches to the right
backend at runtime (detected from the server). Use
`StaticBH backend m a` for type-safe, backend-specific code.


Stability
---------

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.

Testing
-------

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:
1. Get into the Nix environment by running `nix develop` (or `nix-shell` for a non-flake setup)
1. Start Elasticsearch defined by `docker-compose.yml`: `make compose`
1. Run the tests with Cabal: `cabal test`

The second step can be left out if ElasticSearch (or OpenSearch) is started manually.

Contributions
-------------

Any contribution is welcomed, for consistency reason [`ormolu`](https://github.com/tweag/ormolu) is used.

Hackage page and Haddock documentation
======================================

<http://hackage.haskell.org/package/bloodhound>

Elasticsearch Tutorial
======================

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](https://vimeo.com/106463167).

Examples
========

See the [examples](htts://github.com/bitemyapp/bloodhound/tree/master/examples) directory for example code.

Index a document
----------------

```haskell
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
  }
-}
```

Fetch documents
---------------

```haskell
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
    }
-}
```


Contributors
============

* [Chris Allen](https://github.com/bitemyapp)
* [Liam Atkinson](https://github.com/latkins)
* [Christopher Guiney](https://github.com/chrisguiney)
* [Curtis Carter](https://github.com/ccarter)
* [Michael Xavier](https://github.com/MichaelXavier)
* [Bob Long](https://github.com/bobjflong)
* [Maximilian Tagher](https://github.com/MaxGabriel)
* [Anna Kopp](https://github.com/annakopp)
* [Matvey B. Aksenov](https://github.com/supki)
* [Jan-Philip Loos](https://github.com/MaxDaten)
* [Gautier DI FOLCO](https://github.com/blackheaven)

Possible future functionality
=============================

Span Queries
------------

Beginning here: <https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-span-first-query.html>

Node discovery and failover
---------------------------

Might require TCP support.

Support for TCP access to Elasticsearch
---------------------------------------

Pretend to be a transport client?

Bulk cluster-join merge
-----------------------

Might require making a lucene index on disk with the appropriate format.

GeoShapeQuery
-------------

<https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geo-shape-query.html>

Script based sorting
--------------------

<https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html#_script_based_sorting>

Runtime checking for cycles in data structures
----------------------------------------------

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 Origin
============

Photo from HA! Designs: <https://www.flickr.com/photos/hadesigns/>