I am trying to sort the query result according to most similar to the field specify.
Example 1:
terms = "john phoenix"
Repo.all(c in Contact, order_by: similarity_order([c.name, c.city], terms)
Will generate SQL:
select *
from Contact c
order by COALESCE(SIMILARITY(c.name,'john'),0) + COALESCE(SIMILARITY(c.name,'phoenix'),0) +
COALESCE(SIMILARITY(c.city,'john'),0) + COALESCE(SIMILARITY(c.city,'phoenix'),0)
Example 2:
terms = "john phoenix denver"
Repo.all(c in Contact, order_by: similarity_order([c.name, c.city, c.state], terms)
Will generate SQL:
select *
from Contact c
order by COALESCE(SIMILARITY(c.name,'john'),0) +
COALESCE(SIMILARITY(c.name,'phoenix'),0) +
COALESCE(SIMILARITY(c.name,'denver'),0)+
COALESCE(SIMILARITY(c.city,'john'),0) +
COALESCE(SIMILARITY(c.city,'phoenix'),0)+
COALESCE(SIMILARITY(c.city,'denver'),0) +
COALESCE(SIMILARITY(c.state,'john'),0) +
COALESCE(SIMILARITY(c.state,'phoenix'),0)+
COALESCE(SIMILARITY(c.state,'denver'),0)
I don’t seem to be able to compile.
I understand that during compile time param ‘terms’ is nil.
I don’t seem to be able to get ‘terms’ during runtime.
def search_contacts(terms) do
Repo.all(
from cont in Contact,
order_by: similarity_order([cont.name, cont.city], ^terms)
end
defmacro similarity_order(fields, terms) do
texts = String.split(terms, " ")
frag_text =
Enum.map(
1..(Enum.count(fields) * Enum.count(texts)),
fn _ -> "COALESCE(SIMILARITY(?,?),0)" end)
|> Enum.join("+")
fld_values = Enum.flat_map(fields, fn f -> Enum.flat_map(texts, fn t -> [f, t] end) end)
quote do
fragment(unquote(frag_text), unquote_splicing(fld_values))
end
end