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,
|
||||
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
|
||||
table "members"
|
||||
repo Mv.Repo
|
||||
|
|
@ -108,6 +113,47 @@ defmodule Mv.Membership.Member do
|
|||
where [changing(:user)]
|
||||
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
|
||||
|
||||
validations do
|
||||
|
|
@ -281,4 +327,21 @@ defmodule Mv.Membership.Member do
|
|||
identities do
|
||||
identity :unique_email, [:email]
|
||||
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue