Skip to content

Commit

Permalink
Add details to README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
philipbrown committed Mar 21, 2023
1 parent 995f0c5 commit 6b79397
Showing 1 changed file with 68 additions and 5 deletions.
73 changes: 68 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `haystack` to your list of dependencies in `mix.exs`:
Haystack can be installed by adding `haystack` to your list of dependencies in `mix.exs`:

```elixir
def deps do
Expand All @@ -19,6 +18,70 @@ def deps do
end
```

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at <https://hexdocs.pm/haystack>.
The entry point to Haystack is the `Haystack` module. This module is responsible for managing the various indexes you have as part of the project as well as any future configuration or high level concerns.

These conserns are encapsulated in the `%Haystack{}` struct:

```elixir
haystack = Haystack.new()
```

Currently, the `Haystack` module has a single `index/3` function that accepts the name of the index as an atom and a callback function to apply changes to the index. If the index does not already exist, Haystack will create one and pass it into the callback so you can configure or use it:

```elixir
Haystack.index(haystack, :animals, fn index ->
index
end)
```

Once you have an `index`, the first thing you need to do is apply specify the fields of the index:

```elixir
alias Haystack.Index

Haystack.index(haystack, :animals, fn index ->
index
|> Index.ref(Index.Field.term("id"))
|> Index.field(Index.Field.new("name"))
|> Index.field(Index.Field.new("description"))
end)
```

The `ref` is the identifier of the document. You can create as many fields on the document as you want. When you add documents to the index, Haystack will automatically extract the fields you have configured.

You can also provide nested fields using dot syntax:

```elixir
alias Haystack.Index

Haystack.index(haystack, :people, fn index ->
index
|> Index.ref(Index.Field.term("id"))
|> Index.field(Index.Field.new("name"))
|> Index.field(Index.Field.new("address.postcode"))
end)
```

Each Haystack index has a configurable storage implementation. By default the storage implementation is essentially a map, which is great for testing and prototyping, but probably not a good solution if you want to use Haystack as part of a real application. You can configure a custom storage implementation on the index:

```elixir
alias Haystack.{Index, Storage}

Haystack.index(haystack, :animals, fn index ->
index
|> Index.ref(Index.Field.term("id"))
|> Index.field(Index.Field.new("name"))
|> Index.field(Index.Field.new("description"))
|> Index.storage(Storage.ETS.new())
end)
```

The ETS storage implementation is provided as one of the default implementations that ships with Haystack out of the box. If you would like to extend Haystack with your own storage implementation, it's very easy to do so. We'll look at doing that later in this blog post.

Finally, the most important part of a library that provides full-text search is the ability to query the indexes. Here is the most basic version of applying queries:

```elixir
Haystack.index(haystack, :animals, &Index.search(&1, "Red Panda"))
```

This would search the `:animals` index for the phrase `"Red Panda"`. Haystack also offers a powerful way to build and run search queries, which we'll look at later in this blog post.

0 comments on commit 6b79397

Please sign in to comment.