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_name
against.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_type
of:eq
. - This Hook has the default
search_expr
of: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.SimpleSearch
OR
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, %{})
Parent
When 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_term
When 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