Problem
I have a table like this:
product | tags (jsonb) |
---|---|
P001 | [{“name”: “LX”,”active”: true}, {“name”: “TX”,”active”: true}] |
P002 | [{“name”: “LX”,”active”: true}] |
I am trying to query against this table to get a list of products with tags that are the same.
I found the following to be insufficient for my query since it will match all products with at least the tag I query for:
x
SELECT product
FROM product_table
WHERE tags @> '[
{"name": "LX","active": true}
]';
Result
product |
---|
P001 |
P002 |
So I need the match to be more exact without being so strict as to demand order of tag objects in the array. For example:
[
{
"name": "LX",
"active": true
},
{
"name": "TX",
"active": true
}
]
-- Interpreted the same as
[
{
"name": "TX",
"active": true
},
{
"name": "LX",
"active": true
}
]
Desired Result
A list of products that match only the tags in the query.
Resources
A list of the resources I am using to try and solve the problem.
- 9.16. JSON Functions and Operators
- How To Query a JSONB Array of Objects as a Recordset in PostgreSQL
- Working with a JSONB Array of Objects in PostgreSQL
Advertisement
Answer
Base on the example you give, you can use simultaneous containment in both directions.
WHERE tags <@ :whatever and tags @> :whatever
If you don’t like repeating the arguments, you could make a custom function, or operator:
create function equal_but_for_order(jsonb,jsonb) returns boolean language sql as $$
select $1 <@ $2 and $1 @> $2
$$;
create operator <@> (function = equal_but_for_order, leftarg = jsonb, rightarg=jsonb);
WHERE tags <@> :whatever