Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compare numeric in PostgreSQL JSONB

I ran into strange situation working with jsonb type.

Expected behavior


Using short jsonb structure:

{"price": 99.99}

I wrote query like this:

 SELECT * FROM table t WHERE t.data->price > 90.90

And it fail with error operator does not exist: jsonb > numeric the same as text (->>) operator does not exist: text > numeric

Then I wrote comparison as mentioned in many resources:

SELECT * FROM table t WHERE (t.data->>price)::NUMERIC > 90.90

And it's works as expected.

What's strange:


SELECT * FROM table t WHERE t.data->price > '90.90';

a little weird but query above works right.

EXPLAIN: Filter: ((data -> 'price'::text) > '90.90'::jsonb)

But if I change jsonb value to text as: {"price": "99.99"} there is no result any more - empty.

Question: How actually PostgreSQL compare numeric data and what preferable way to do this kind of comparison.

like image 974
user1156168 Avatar asked Dec 18 '18 22:12

user1156168


People also ask

How do I query Jsonb data in PostgreSQL?

Querying the JSON documentPostgreSQL has two native operators -> and ->> to query JSON documents. The first operator -> returns a JSON object, while the operator ->> returns text. These operators work on both JSON as well as JSONB columns. There are additional operators available for JSONB columns.

Can you index Jsonb Postgres?

JSONB and IndexesPostgreSQL can use indexes for the text results as compare operands. GIN index can be used by the GIN JSONB operator class.

Is Jsonb better than JSON?

The json data type stores an exact copy of the input text, which processing functions must reparse on each execution; while jsonb data is stored in a decomposed binary format that makes it slightly slower to input due to added conversion overhead, but significantly faster to process, since no reparsing is needed.

Is Postgres Jsonb fast?

Because JSONB stores data in a binary format, queries process significantly faster. Storing data in binary form allows Postgres to access a particular JSON key-value pair without reading the entire JSON record. The reduced disk load speeds up overall performance. Support for indexing.


1 Answers

But you aren't comparing numeric data, are you.

I can see that you think price contains a number, but it doesn't. It contains a JSON value. That might be a number, or it might be text, or an array, or an object, or an object containing arrays of objects containing...

You might say "but the key is called 'price' of course it is a number" but that's no use to PostgreSQL, particularly if I come along and sneakily insert an object containing arrays of objects containing...1

So - if you want a number to compare to you need convert it to a number (t.data->>price)::NUMERIC or convert your target value to JSON and let PostgreSQL do a JSON-based comparison (which might do what you want, it might not - I don't know what the exact rules are for JSON).


1 And that's exactly the sort of thing I would do, even though it is Christmas. I'm a bad person.

like image 105
Richard Huxton Avatar answered Nov 15 '22 04:11

Richard Huxton