If you have table like:
create table(:foos) do
add :data, :json
end
create index(:foos, [:data], using: :gin])
Then queries that use json_extract_path/2, or equivalent Access-like syntax, will not utilise that index. In other words:
from foo in Foo,
where: foo.data["bar"] == "yay"
Will require full table scan, and can kill performance of your queries.
There are 2 solutions to this problem:
- If you know the subset of queried fields beforehand, then you can create functional index on these fields, for example
create index(:foos, ["(data#>'{bar}'"]) - If you do not know the subset of fields and want to run queries on arbitrary path, then instead you should use
fragment/1with@>operator, so in this case it would befrom foo in Foo, where: fragment("? @> ?", foo.data, ~S({"bar": "yay"}})). Beware that this have different behaviour when working with arrays.


















