Обсуждение: Inconsistent Behavior in JSONB Numeric Array Deletion
Hi all,
I’d like to report what I believe is an inconsistency in the behavior of the jsonb - operator when applied to numeric arrays.
Problem
PostgreSQL allows us to check for the presence of a scalar inside a JSONB array:
SELECT jsonb('[2,3,1]') @> to_jsonb(1);
-- Returns true
However, when attempting to remove that value from the array using -, the operation fails:
SELECT jsonb('[2,3,1]') - to_jsonb(1);
-- ERROR: operator does not exist: jsonb - jsonb
-- HINT: You might need to add explicit type casts.
This behavior differs from index-based removal:
SELECT jsonb('[2,3,1]') - 1;
-- Returns [2, 1]
But logically, if @> to_jsonb(1) is true, then jsonb('[2,3,1]') - to_jsonb(1) should remove the value, not the index.
Proposal
Support a jsonb - jsonb operator where, if the RHS is a scalar that appears in the LHS array, the operator removes all matching values:
SELECT jsonb('[2,3,1]') - to_jsonb(1);
-- Expected: [2, 3]
This would mirror similar behavior in many application languages and allow value-based deletion from JSON arrays without casting back to SQL arrays or using procedural workarounds.
Impact
The absence of this capability creates a gap in value-level JSONB manipulation. Developers often have to resort to:
- Procedural code in PL/pgSQL
- Transforming JSONB arrays into SQL arrays (with limited type support)
- Writing client-side logic
Adding support for this behavior would simplify many API use cases involving JSON state manipulation.
Happy to clarify further or contribute a patch.
Best regards,
Mark Drake
On Tue, Jun 10, 2025 at 4:52 PM Mark Dake <mark.drake@golden-hind.com> wrote: > SELECT jsonb('[2,3,1]') @> to_jsonb(1); > -- Returns true > > However, when attempting to remove that value from the array using -, the operation fails: > SELECT jsonb('[2,3,1]') - to_jsonb(1); > -- ERROR: operator does not exist: jsonb - jsonb > -- HINT: You might need to add explicit type casts. > > This behavior differs from index-based removal: > SELECT jsonb('[2,3,1]') - 1; > -- Returns [2, 1] > > But logically, if @> to_jsonb(1) is true, then jsonb('[2,3,1]') - to_jsonb(1) should remove the value, not the index. I don't see how you can say that there's anything inconsistent here. The proposed behavior of the operator you want to add would be inconsistent with the existing integer subtraction operator, because the former would remove by value and the latter removes by index. But there's no inconsistency right now because the operator you want to add doesn't exist yet. And I don't think the fact that @>(jsonb,jsonb) exists can reasonably be said to be inconsistent with the fact that -(jsonb,jsonb) doesn't, either. Now, none of that means that we couldn't define -(jsonb,jsonb) in the manner you propose. But that's just a feature idea, not an inconsistency. -- Robert Haas EDB: http://www.enterprisedb.com