darnahsan
I am trying to implement custom filters on a table that has a jsonb column metadata using Flop. as per @woylie suggestions trying to use custom fields
Following the docs for custom fields came up with below code.
when trying to lookup metadata_is_active getting error
Postgrex expected a binary, got true. Please make sure the value you are passing matches the definition in your table or in your query or convert the value accordingly.
<url>?filters[0][field]=name&filters[0][value]=Expert&filters[1][field]=whatsapp_no&filters[1][value]=88827271111&filters[2][field]=metadata_is_active&filters[2][value]=true
for metadata_owner it throws no error just returns empty result even on values that should match
<url>?filters[0][field]=name&filters[0][value]=Expert&filters[1][field]=whatsapp_no&filters[1][value]=88827271111&filters[2][field]=metadata_owner&filters[2][value]=abc
I feel my noobness with dynamic and fragmented queries is probably where I am wrong.
organization.ex
@derive {
Flop.Schema,
filterable: [:name, :whatsapp_no, :metadata_is_active, :metadata_owner],
sortable: [:name, :whatsapp_no, :inserted_at],
max_limit: 100,
default_limit: 50,
adapter_opts: [
custom_fields: [
metadata_is_active: [
filter: {OrganizationMetadataFilters, :metadata, []},
ecto_type: :boolean
],
metadata_owner: [
filter: {OrganizationMetadataFilters, :metadata, []},
ecto_type: :string
]
]
]
}
schema "organizations" do
field :name, :string
field :whatsapp_no, :string
embeds_one :metadata, OrganizationMetadata
organization_metadata_filters.ex
defmodule Maverick.Organizations.OrganizationMetadataFilters do
@moduledoc """
Maverick.Organizations.MetadataFilters
"""
import Ecto.Query
def metadata(query, %Flop.Filter{field: name, value: value, op: op} = flop_filter, _) do
metadata_field = field(name)
metadata_value = value(name, value)
expr =
dynamic(
[r],
fragment(
"metadata->>'?'",
field(r, ^metadata_field)
)
)
case metadata_value do
{:ok, query_value} ->
IO.inspect(flop_filter, label: "Flop filter")
IO.inspect(metadata_field, label: "Metadata field")
IO.inspect(query_value, label: "Metadata value")
conditions =
case op do
:== -> dynamic([r], ^expr == ^query_value)
:!= -> dynamic([r], ^expr != ^query_value)
:> -> dynamic([r], ^expr > ^query_value)
:< -> dynamic([r], ^expr < ^query_value)
:>= -> dynamic([r], ^expr >= ^query_value)
:<= -> dynamic([r], ^expr <= ^query_value)
end
IO.inspect(conditions, label: "conditions")
where(query, ^conditions)
:error ->
IO.inspect("Error casting value #{value} for #{name}")
query
end
end
def field(:metadata_is_active), do: :is_active
def field(:metadata_owner), do: :owner
def value(:metadata_is_active, value), do: Ecto.Type.cast(:boolean, value)
def value(:metadata_owner, value), do: Ecto.Type.cast(:string, value)
end
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixirconf-us
- #elixir-ls
- #ai
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming











Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
woylie
As per documentation,
->>gets an object field as text, but you try to pass a boolean. Try changingecto_typeto:string.darnahsan
Thanks for the link. With explicit type casting the 1st error is resolved but now I see the same empty result for both fields which mean they are not matching somehow.
Also the wierd part is I see that
metadatafunction is called twice for each request, is that expected ?woylie
Could you output the actual SQL? (Flop.validate → Flop.query → Ecto.Adapters.SQL.to_sql)
If you use offset/page-based pagination, Flop makes a second query to retrieve the total count. The parameters are only validated once, but the
whereclauses are built once for the main query and once for the count query.darnahsan
Seems there is an error in
Flop.validatewhen sending boolean value which then doesn’t add the custom fields to the query, hence no results. Below is the outputFlop.validateFlop.query → → Ecto.Adapters.SQL.to_sql
For the string field there is no error and query seem ok
Flop validate:Flop.query -> → Ecto.Adapters.SQL.to_sqlwoylie
The schema config in your first post uses
metadata_is_activeas custom field name, but the parameters usemetadata_active.darnahsan
I updated it from
is_activetoactiveto match the key in jsonb, itsactiveeverywhere nowdarnahsan
on changing the ecto_type to string in Flop schema it works fine as the incoming param from request is a string
Flop validate:Flop RAW SQLdarnahsan
shouldn’t this be
something like this ?
o0.metadata->>'active'similarly
(metadata->>'o0."owner"')as(o0.metadata->>'owner')darnahsan
doing so fixes it for now
Flop RAW SQLThanks for you help @woylie , I have another query for
:inop, will discuss separatelybalanza
Hi @darnahsan,
thanks for starting this thread, it’s currently the only example reference for querying JSONB with Flop.
I created a small project implementing your example, I hope it doesn’t bother you. You can find it at GitHub - balanza/example-elixir-flop-postgres-jsonb · GitHub.
I tried to fill the gaps with some boilerplate code. However, my implementation doesn’t work: the custom filter is not invoked.
If you want to try:
As you can see, the field is evalued just like it belongs to the original
Organizationschema.