feat(member). added search action to ressource
This commit is contained in:
parent
c7c6d329fb
commit
f6bfeadb7b
1 changed files with 63 additions and 0 deletions
|
|
@ -3,6 +3,11 @@ defmodule Mv.Membership.Member do
|
||||||
domain: Mv.Membership,
|
domain: Mv.Membership,
|
||||||
data_layer: AshPostgres.DataLayer
|
data_layer: AshPostgres.DataLayer
|
||||||
|
|
||||||
|
require Ash.Query
|
||||||
|
import Ash.Expr
|
||||||
|
|
||||||
|
@default_fields [:first_name, :last_name, :email, :phone_number, :city, :street, :house_number, :postal_code]
|
||||||
|
|
||||||
postgres do
|
postgres do
|
||||||
table "members"
|
table "members"
|
||||||
repo Mv.Repo
|
repo Mv.Repo
|
||||||
|
|
@ -108,6 +113,47 @@ defmodule Mv.Membership.Member do
|
||||||
where [changing(:user)]
|
where [changing(:user)]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
read :search do
|
||||||
|
argument :query, :string, allow_nil?: true
|
||||||
|
argument :fields, {:array, :atom}, allow_nil?: true
|
||||||
|
argument :similarity_threshold, :float, allow_nil?: true
|
||||||
|
|
||||||
|
prepare fn query, _ctx ->
|
||||||
|
q = Ash.Query.get_argument(query, :query) || ""
|
||||||
|
fields = Ash.Query.get_argument(query, :fields) || @default_fields
|
||||||
|
threshold = Ash.Query.get_argument(query, :similarity_threshold) || 0.2
|
||||||
|
|
||||||
|
if is_binary(q) and String.trim(q) != "" do
|
||||||
|
q2 = String.trim(q)
|
||||||
|
pat = "%" <> q2 <> "%"
|
||||||
|
|
||||||
|
# FTS as main filter and fuzzy search just fo first name, last name and strees
|
||||||
|
query
|
||||||
|
|> Ash.Query.filter(
|
||||||
|
expr(
|
||||||
|
fragment("search_vector @@ websearch_to_tsquery('simple', ?)", ^q2) or
|
||||||
|
fragment("search_vector @@ plainto_tsquery('simple', ?)", ^q2) or
|
||||||
|
# Substring on numeric-like fields (best effort, supports middle substrings)
|
||||||
|
contains(postal_code, ^q2) or
|
||||||
|
contains(house_number, ^q2) or
|
||||||
|
contains(phone_number, ^q2) or
|
||||||
|
fragment("? % first_name", ^q2) or
|
||||||
|
fragment("? % last_name", ^q2) or
|
||||||
|
fragment("? % street", ^q2) or
|
||||||
|
fragment("word_similarity(?, first_name) > ?", ^q2, ^threshold) or
|
||||||
|
fragment("word_similarity(?, last_name) > ?", ^q2, ^threshold) or
|
||||||
|
fragment("word_similarity(?, street) > ?", ^q2, ^threshold) or
|
||||||
|
fragment("similarity(first_name, ?) > ?", ^q2, ^threshold) or
|
||||||
|
fragment("similarity(last_name, ?) > ?", ^q2, ^threshold) or
|
||||||
|
fragment("similarity(street, ?) > ?", ^q2, ^threshold)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else
|
||||||
|
query
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
validations do
|
validations do
|
||||||
|
|
@ -281,4 +327,21 @@ defmodule Mv.Membership.Member do
|
||||||
identities do
|
identities do
|
||||||
identity :unique_email, [:email]
|
identity :unique_email, [:email]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Fuzzy Search function that can be called by live view and calls search action
|
||||||
|
def fuzzy_search(query, opts) do
|
||||||
|
q = (opts[:query] || opts["query"] || "") |> to_string()
|
||||||
|
|
||||||
|
if String.trim(q) == "" do
|
||||||
|
query
|
||||||
|
else
|
||||||
|
args =
|
||||||
|
case (opts[:fields] || opts["fields"]) do
|
||||||
|
nil -> %{query: q}
|
||||||
|
fields -> %{query: q, fields: fields}
|
||||||
|
end
|
||||||
|
|
||||||
|
Ash.Query.for_read(query, :search, args)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue