diff --git a/lib/membership/member.ex b/lib/membership/member.ex index 78f42f7..4c1a156 100644 --- a/lib/membership/member.ex +++ b/lib/membership/member.ex @@ -529,12 +529,11 @@ defmodule Mv.Membership.Member do # Builds search filter for custom field values using LIKE on JSONB # Note: LIKE on JSONB is not index-optimized, may be slow with many custom fields # This is a fallback for substring matching in custom fields (e.g., phone numbers) + # Uses ->> operator which always returns TEXT directly (no need for -> + ::text fallback) defp build_custom_field_filter(pattern) do expr( fragment( - "EXISTS (SELECT 1 FROM custom_field_values WHERE member_id = id AND (value->>'_union_value' LIKE ? OR value->>'value' LIKE ? OR (value->'_union_value')::text LIKE ? OR (value->'value')::text LIKE ?))", - ^pattern, - ^pattern, + "EXISTS (SELECT 1 FROM custom_field_values WHERE member_id = id AND (value->>'_union_value' LIKE ? OR value->>'value' LIKE ?))", ^pattern, ^pattern ) diff --git a/priv/repo/migrations/20251204123714_add_custom_field_values_to_search_vector.exs b/priv/repo/migrations/20251204123714_add_custom_field_values_to_search_vector.exs index 1c8fbc9..45a12e1 100644 --- a/priv/repo/migrations/20251204123714_add_custom_field_values_to_search_vector.exs +++ b/priv/repo/migrations/20251204123714_add_custom_field_values_to_search_vector.exs @@ -20,23 +20,11 @@ defmodule Mv.Repo.Migrations.AddCustomFieldValuesToSearchVector do BEGIN -- Aggregate all custom field values for this member -- Support both formats: _union_type/_union_value (Ash format) and type/value (legacy) - -- Extract value as text: handle both string and numeric values correctly + -- ->> operator always returns TEXT directly (no need for -> + ::text fallback) SELECT string_agg( CASE - -- Try _union_value first (Ash format) - WHEN value ? '_union_value' THEN - -- For strings: value->>'_union_value' returns text directly - -- For numbers/booleans: value->'_union_value' returns JSONB, then ::text converts it - COALESCE( - NULLIF(value->>'_union_value', ''), - (value->'_union_value')::text - ) - -- Fallback to value (legacy format) - WHEN value ? 'value' THEN - COALESCE( - NULLIF(value->>'value', ''), - (value->'value')::text - ) + WHEN value ? '_union_value' THEN value->>'_union_value' + WHEN value ? 'value' THEN value->>'value' ELSE '' END, ' ' @@ -94,20 +82,17 @@ defmodule Mv.Repo.Migrations.AddCustomFieldValuesToSearchVector do -- If value hasn't changed, we can skip the expensive re-aggregation IF TG_OP = 'UPDATE' THEN -- Extract OLD value for comparison (handle both JSONB formats) + -- ->> operator always returns TEXT directly old_value_text := COALESCE( NULLIF(OLD.value->>'_union_value', ''), - (OLD.value->'_union_value')::text, NULLIF(OLD.value->>'value', ''), - (OLD.value->'value')::text, '' ); -- Extract NEW value for comparison (handle both JSONB formats) new_value_text := COALESCE( NULLIF(NEW.value->>'_union_value', ''), - (NEW.value->'_union_value')::text, NULLIF(NEW.value->>'value', ''), - (NEW.value->'value')::text, '' ); @@ -150,21 +135,11 @@ defmodule Mv.Repo.Migrations.AddCustomFieldValuesToSearchVector do -- Aggregate all custom field values for this member -- Support both formats: _union_type/_union_value (Ash format) and type/value (legacy) - -- Extract value as text: handle both string and numeric values correctly + -- ->> operator always returns TEXT directly SELECT string_agg( CASE - -- Try _union_value first (Ash format) - WHEN value ? '_union_value' THEN - COALESCE( - NULLIF(value->>'_union_value', ''), - (value->'_union_value')::text - ) - -- Fallback to value (legacy format) - WHEN value ? 'value' THEN - COALESCE( - NULLIF(value->>'value', ''), - (value->'value')::text - ) + WHEN value ? '_union_value' THEN value->>'_union_value' + WHEN value ? 'value' THEN value->>'value' ELSE '' END, ' ' @@ -221,18 +196,8 @@ defmodule Mv.Repo.Migrations.AddCustomFieldValuesToSearchVector do setweight(to_tsvector('simple', coalesce( (SELECT string_agg( CASE - -- Try _union_value first (Ash format) - WHEN value ? '_union_value' THEN - COALESCE( - NULLIF(value->>'_union_value', ''), - (value->'_union_value')::text - ) - -- Fallback to value (legacy format) - WHEN value ? 'value' THEN - COALESCE( - NULLIF(value->>'value', ''), - (value->'value')::text - ) + WHEN value ? '_union_value' THEN value->>'_union_value' + WHEN value ? 'value' THEN value->>'value' ELSE '' END, ' '