Rummage.Ecto v2.0.0 Rummage.Ecto.CustomHook.SimpleSearch View Source
Rummage.Ecto.CustomHook.SimpleSearch is an example of a Custom Hook that
comes with Rummage.Ecto.
This module provides a operations that can add searching functionality to
a pipeline of Ecto queries. This module works by taking fields, and
search_type and search_term.
This module doesn't support associations and hence is a simple alternative to Rummage's default search hook.
NOTE: This module doesn't return a list of entries, but a Ecto.Query.t.
This module uses Rummage.Ecto.Hook.
ABOUT:
Arguments:
This Hook expects a queryable (an Ecto.Queryable) and
search_params (a Map). The map should be in the format:
%{field_name: %{search_term: true, search_type: :eq}}
Details:
field_name: The field name to search by.search_term: Term to compare thefield_nameagainst.search_type: Determines the kind of search to perform. If:eq, itexpects the `field_name`'s value to be equal to `search_term`, If `lt`, it expects it to be less than `search_term`. To see all the `search_type`s, check `Rummage.Ecto.Services.BuildSearchQuery`search_expr: This is optional. Defaults to:where. This is the way thesearch expression is appended to the existing query. To see all the `search_expr`s, check `Rummage.Ecto.Services.BuildSearchQuery`
For example, if we want to search products with available = true, we would
do the following:
Rummage.Ecto.CustomHook.SimpleSearch.run(Product, %{available:
%{search_type: :eq,
search_term: true}})This can be used for a search with multiple fields as well. Say, we want to
search for products that are available, but have a price less than 10.0.
Rummage.Ecto.CustomHook.SimpleSearch.run(Product,
%{available: %{search_type: :eq,
search_term: true},
%{price: %{search_type: :lt,
search_term: 10.0}})Assoications:
This module doesn't support assocations.
ASSUMPTIONS/NOTES:
- This Hook assumes that the searched field is a part of the schema passed
as the
queryable. - This Hook has the default
search_typeof:eq. - This Hook has the default
search_exprof:where.
USAGE:
For a regular search:
This returns a queryable which upon running will give a list of Parent(s)
searched by ascending field_1
alias Rummage.Ecto.CustomHook.SimpleSearch
searched_queryable = SimpleSearch.run(Parent,
%{field_1: %{search_type: :like, search_term: "field_!"}}})
For a case-insensitive search:
This returns a queryable which upon running will give a list of Parent(s)
searched by ascending case insensitive field_1.
Keep in mind that case_insensitive can only be called for text fields
alias Rummage.Ecto.CustomHook.SimpleSearch
searched_queryable = SimpleSearch.run(Parent,
%{field_1: %{ search_type: "ilike", search_term: "field_!"}}})
There are many other search_types. Check out
Rummage.Ecto.Services.BuildSearchQuery docs to explore more search_types.
This module can be used by overriding the default module. This can be done in the following ways:
In the Rummage.Ecto call:
Rummage.Ecto.rummage(queryable, rummage,
search: Rummage.Ecto.CustomHook.SimpleSearch)
or
MySchema.rummage(rummage, search: Rummage.Ecto.CustomHook.SimpleSearch)OR
Globally for all models in config.exs:
config :my_app,
Rummage.Ecto,
search: Rummage.Ecto.CustomHook.SimpleSearchOR
When using Rummage.Ecto with an Ecto.Schema:
defmodule MySchema do
use Rummage.Ecto, repo: SomeRepo,
search: Rummage.Ecto.CustomHook.SimpleSearch
end Link to this section Summary
Functions
Callback implementation for Rummage.Ecto.Hook.format_params/3.
This is the callback implementation of Rummage.Ecto.Hook.run/2.
Link to this section Functions
Specs
format_params(Ecto.Query.t(), map(), keyword()) :: map()
format_params(Ecto.Query.t(), map(), keyword()) :: map()
Callback implementation for Rummage.Ecto.Hook.format_params/3.
This function ensures that params for each field have keys assoc, search_type and
search_expr which are essential for running this hook module.
Examples
iex> alias Rummage.Ecto.CustomHook.SimpleSearch
iex> SimpleSearch.format_params(Parent, %{field: %{}}, [])
%{field: %{search_expr: :where, search_type: :eq}} Specs
run(Ecto.Query.t(), map()) :: Ecto.Query.t()
run(Ecto.Query.t(), map()) :: Ecto.Query.t()
This is the callback implementation of Rummage.Ecto.Hook.run/2.
Builds a search Ecto.Query.t on top of a given Ecto.Query.t variable
with given params.
Besides an Ecto.Query.t an Ecto.Schema module can also be passed as it
implements Ecto.Queryable
Params is a Map, keys of which are field names which will be searched for and
value corresponding to that key is a list of params for that key, which
should include the keys: #{Enum.join(@expected_keys, ", ")}.
This function expects a search_expr, search_type.
The search_term is what the field
will be matched to based on the search_type and search_expr.
If no search_expr is given, it defaults to where.
For all search_exprs, refer to Rummage.Ecto.Services.BuildSearchQuery.
For all search_types, refer to Rummage.Ecto.Services.BuildSearchQuery.
If an expected key isn't given, a Runtime Error is raised.
NOTE:This hook isn't responsible for doing type validations. That's the
responsibility of the user sending search_term and search_type.
Examples
When search_params are empty, it simply returns the same queryable:
iex> alias Rummage.Ecto.CustomHook.SimpleSearch
iex> import Ecto.Query
iex> SimpleSearch.run(Parent, %{})
ParentWhen a non-empty map is passed as a field params, but with a missing key:
iex> alias Rummage.Ecto.CustomHook.SimpleSearch
iex> import Ecto.Query
iex> SimpleSearch.run(Parent, %{field: %{search_type: :eq}})
** (RuntimeError) Error in params, No values given for keys: search_termWhen a valid map of params is passed with an Ecto.Schema module:
iex> alias Rummage.Ecto.CustomHook.SimpleSearch
iex> import Ecto.Query
iex> search_params = %{field1: %{
...> search_type: :like,
...> search_term: "field1",
...> search_expr: :where}}
iex> SimpleSearch.run(Rummage.Ecto.Product, search_params)
#Ecto.Query<from p0 in subquery(from p0 in Rummage.Ecto.Product), where: like(p0.field1, ^"%field1%")>When a valid map of params is passed with an Ecto.Query.t:
iex> alias Rummage.Ecto.CustomHook.SimpleSearch
iex> import Ecto.Query
iex> search_params = %{field1: %{
...> search_type: :like,
...> search_term: "field1",
...> search_expr: :where}}
iex> query = from p0 in "products"
iex> SimpleSearch.run(query, search_params)
#Ecto.Query<from p0 in subquery(from p0 in "products"), where: like(p0.field1, ^"%field1%")>When a valid map of params is passed with an Ecto.Query.t and :on_where:
iex> alias Rummage.Ecto.CustomHook.SimpleSearch
iex> import Ecto.Query
iex> search_params = %{field1: %{
...> search_type: :like,
...> search_term: "field1",
...> search_expr: :or_where}}
iex> query = from p0 in "products"
iex> SimpleSearch.run(query, search_params)
#Ecto.Query<from p0 in subquery(from p0 in "products"), or_where: like(p0.field1, ^"%field1%")>When a valid map of params is passed with an Ecto.Query.t, searching on
a boolean param
iex> alias Rummage.Ecto.CustomHook.SimpleSearch
iex> import Ecto.Query
iex> search_params = %{available: %{
...> search_type: :eq,
...> search_term: true,
...> search_expr: :where}}
iex> query = from p0 in "products"
iex> SimpleSearch.run(query, search_params)
#Ecto.Query<from p0 in subquery(from p0 in "products"), where: p0.available == ^true>When a valid map of params is passed with an Ecto.Query.t, searching on
a float param
iex> alias Rummage.Ecto.CustomHook.SimpleSearch
iex> import Ecto.Query
iex> search_params = %{price: %{
...> search_type: :gteq,
...> search_term: 10.0,
...> search_expr: :where}}
iex> query = from p0 in "products"
iex> SimpleSearch.run(query, search_params)
#Ecto.Query<from p0 in subquery(from p0 in "products"), where: p0.price >= ^10.0>When a valid map of params is passed with an Ecto.Query.t, searching on
a boolean param, but with a wrong search_type.
NOTE: This doesn't validate the search_type of search_term
iex> alias Rummage.Ecto.CustomHook.SimpleSearch
iex> import Ecto.Query
iex> search_params = %{available: %{
...> search_type: :ilike,
...> search_term: true,
...> search_expr: :where}}
iex> query = from p0 in "products"
iex> SimpleSearch.run(query, search_params)
** (ArgumentError) argument error