If I have large nested maps in jsonb columns and I just want to update one value, can ash_postgres update the value only without sending the whole JSON of the map again?
Can it use jsonb_set or concatenation like the example from these answers?
If I have large nested maps in jsonb columns and I just want to update one value, can ash_postgres update the value only without sending the whole JSON of the map again?
Can it use jsonb_set or concatenation like the example from these answers?
Yes.
change atomic_update(:attribute, expr(fragment("")))
or
in a custom change using Ash.Changeset.atomic_update
I get this error trying to use expr and fragment.
“Type Ash.Type.Map
does not support atomic updates with expressions”
attribute :data, :map do
allow_nil? true
public? true
end
update :update do
...
change atomic_update(:data, expr(fragment("data || jsonb_build_object('status', 'test')")))
change atomic_update(:data, expr(fragment("'test'")))
change atomic_update(:data, expr(fragment("")))
end
error #=> %Ash.Error.Invalid{
changeset: "#Changeset<>",
errors: [
%Ash.Error.Changes.InvalidChanges{
fields: nil,
message: "Cannot atomically update MyApp.Schemas.Entity.data: Type `Ash.Type.Map` does not support atomic updates with expressions",
validation: nil,
value: nil,
splode: Ash.Error,
bread_crumbs: [],
vars: [],
path: [],
stacktrace: #Splode.Stacktrace<>,
class: :invalid
}
]
}
We need to document this better, but you can wrap the expression in {:atomic, expr(...)}
to indicate that you’re handing any necessary type casting etc.
I don’t get the error with cast_atomic?: false
.
change atomic_update(:data, expr(fragment("data || jsonb_build_object('status', 'test')")), cast_atomic?: false)
{:atomic, expr(...)}
worked. Is it different from cast_atomic?: false
?
I actually forgot that we had cast_atomic?: false
They are equivalent.