# Hui 辉 [![Build Status](]( [![Hex pm](](
Hui 辉 ("shine" in Chinese) is a [Solr]( client and library for Elixir.

## Usage

Hui enables [Solr]( data querying and other forms of interaction (forthcoming)
in [Elixir]( or [Phoenix]( applications.
The data can be contained within a core (index) held on a single server or a data collection in distributed server architecture (cloud).

### Example

  Hui.q("scott") # keywords search
  Hui.q(q: "loch", rows: 5, fq: ["type:illustration", "format:image/jpeg"])

The above queries a default Solr endpoint - see `Configuration` below.
A query may involve search words (string) or a [Keyword list](
of Solr parameters, invoking the comprehensive and powerful features of Solr.

Queries may also be issued to other specific endpoints and request handlers defined in various formats:

  # URL binary string"http://localhost:8983/solr/collection", q: "loch")

  # URL key referring to an endpoint in configuration - see "Configuration"
  url = :library, q: "edinburgh", rows: 10)

  # URL in a struct
  url = %Hui.URL{url: "http://localhost:8983/solr/collection", handler: "suggest"}, suggest: true, "suggest.dictionary": "mySuggester", "suggest.q": "el")
  # this -> http://http://localhost:8983/solr/collection/suggest?suggest=true&suggest.dictionary=mySuggester&suggest.q=el


See `` in API reference and [Solr reference guide](
for more details on available search parameters.

### HTTP headers and options
HTTP headers and options can be specified via the `t:Hui.URL.t/0` struct.

  # setting up a header and a 10s receiving connection timeout
  url = %Hui.URL{url: "..", headers: [{"accept", "application/json"}], options: [recv_timeout: 10000]}, q: "solr rocks")

See `` for more details. 

Headers and options for a specific endpoint may also be configured - see "Configuration".

### Software library

See [API reference]( for 
available modules and data structures which can also be used for developing Solr
search application in Elixir and Phoenix.

The following [structs]( modules
can be used to generate and encode Solr parameters in more **idiomatic** and **structured** ways.

- Standard and common query struct: `Hui.Q`
- Faceting struct: `Hui.F`, `Hui.F.Range`, `Hui.F.Interval`
- *structs for other request handlers are forthcoming*

For example, instead of prefixing and repeating `fq=filter`, `facet.field=fieldname`, ``,
multiple filter and facet fields can be specified using
`fq: ["field1", "field2"]`, `field: ["field1", "field2"]`, `gap: 10` Elixir codes.

"Per-field" faceting for multiple ranges and intervals can be specified in a succinct and unified
way e.g. `gap` instead of the long-winded `f.[fieldname]` (per field) or ``
(single field range). Per-field use case for a facet can easily be set (or unset) through the `per_field`
field - see below.

  x = %Hui.Q{q: "loch", fq: ["type:image/jpeg", "year:2001"], fl: "id,title", rows: 20}
  x |> Hui.URL.encode_query
  # -> "fl=id%2Ctitle&fq=type%3Aimage%2Fjpeg&fq=year%3A2001&q=loch&rows=20"

  x = %Hui.F{field: ["type", "year", "subject"], query: "edited:true"}
  x |> Hui.URL.encode_query
  # -> "facet=true&facet.field=type&facet.field=year&facet.field=subject&facet.query=edited%3Atrue"
  # there's no need to set "facet: true" as it is implied and a default setting in the struct

  # a unified way to specify per-field or singe-field range
  x = %Hui.F.Range{range: "age", gap: 10, start: 0, end: 100}
  x |> Hui.URL.encode_query
  # -> "facet.range.end=100&"
  x = %{x | per_field: true} # toggle per field faceting
  x |> Hui.URL.encode_query
  # -> "f.age.facet.range.end=100&"

The structs also provide a binding and introspection of available fields.

  iex> %Hui.F{field: ["type", "year"], query: "year:[2000 TO NOW]"}
    contains: nil,
    "contains.ignoreCase": nil,
    "enum.cache.minDf": nil,
    excludeTerms: nil,
    exists: nil,
    facet: true,
    field: ["type", "year"],
    interval: nil,
    limit: nil,
    matches: nil,
    method: nil,
    mincount: nil,
    missing: nil,
    offset: nil,
    "overrequest.count": nil,
    "overrequest.ratio": nil,
    pivot: [],
    "pivot.mincount": nil,
    prefix: nil,
    query: "year:[2000 TO NOW]",
    range: nil,
    sort: nil,
    threads: nil

### Parsing Solr results

Hui returns Solr results as `HTTPoison.Response` struct which contains the Solr response (body).

    body: "...[Solr reponse]..",
    headers: [
      {"Content-Type", "application/json;charset=utf-8"},
      {"Content-Length", "4005"}
    request_url: "http://localhost:8983/solr/gettingstarted/select?q=%2A",
    status_code: 200

JSON response is parsed and decoded as
It is accessible via the `body` key.

  {status, resp} = Hui.q(solr_params)

  # getting a list of Solr documents (in Map)
  solr_docs = resp.body["response"]["docs"]
  total_hits = resp.body["response"]["numFound"]

**Note**: for other response formats such as XML, raw response (text) is currently being returned.

### Other low-level HTTP client features

Under the hood, Hui uses `HTTPoison` - an HTTP client to interact with Solr.
The existing low-level functions of HTTPoison e.g. `get/1`, `get/3`
remain available in the `Hui.Search` module.

## Installation

Hui is [available in Hex](, the package can be installed
by adding `hui` to your list of dependencies in `mix.exs`:

  def deps do
      {:hui, "~> 0.5.1"}

Then run `$ mix deps.get`.

Documentation can be found at [](

## Configuration

A default Solr endpoint may be specified in the application configuration as below:

  config :hui, :default,
    url: "http://localhost:8983/solr/gettingstarted",
    handler: "select", # optional
    headers: [{"accept", "application/json"}], # optional
    options: [recv_timeout: 10000] # optional

HTTP headers and options may also be configured.

See `Hui.URL.default_url!/0`.

Solr provides [various request
for many purposes (search, autosuggest, spellcheck, indexing etc.). The handlers are configured
in different custom or normative names in
[Solr configuration](,
e.g. "select" for search queries.

Additional endpoints and request handlers can be configured in Hui using arbitrary config keys (e.g. `:suggester`):

  config :hui, :suggester,
    url: "http://localhost:8983/solr/collection",
    handler: "suggest"

Use the config key in `` to send queries to the endpoint or retrieve URL settings from configuration e.g. `Hui.URL.configured_url/1`.

## License

Hui is released under Apache 2 License. Check the [LICENSE]( file for more information.