1

In my table I've got column facebook where I store facebook data ( comment count, share count etc.) and It's an array. For example:

{{total_count,14},{comment_count,0},{comment_plugin_count,0},{share_count,12},{reaction_count,2}}

Now I'm trying to SELECT rows that facebook total_count is between 5 and 10. I've tried this:

SELECT * FROM pl where regexp_matches(array_to_string(facebook, ' '), '(\d+).*')::numeric[] BETWEEN 5 and 10;

But I'm getting an error:

ERROR: operator does not exist: numeric[] >= integer

Any ideas?

1
  • total_count is always first?.. Commented Dec 6, 2017 at 16:22

1 Answer 1

1

There is no need to convert the array to text and use regexp. You can access a particular element of the array, e.g.:

with pl(facebook) as (
values ('{{total_count,14},{comment_count,0},{comment_plugin_count,0},{share_count,12},{reaction_count,2}}'::text[])
)

select facebook[1][2] as total_count
from pl;

 total_count 
-------------
 14
(1 row) 

Your query may look like this:

select *
from pl 
where facebook[1][2]::numeric between 5 and 10

Update. You could avoid the troubles described in the comments if you would use the word null instead of empty strings ''''.

with pl(id, facebook) as (
values 
    (1, '{{total_count,14},{comment_count,0}}'::text[]),
    (2, '{{total_count,null},{comment_count,null}}'::text[]),
    (3, '{{total_count,7},{comment_count,10}}'::text[])
)

select *
from pl 
where facebook[1][2]::numeric between 5 and 10

 id |               facebook               
----+--------------------------------------
  3 | {{total_count,7},{comment_count,10}}
(1 row) 

However, it would be unfair to leave your problems without an additional comment. The case is suitable as an example for the lecture How not to use arrays in Postgres. You have at least a few better options. The most performant and natural is to simply use regular integer columns:

create table pl (
    ...
    facebook_total_count integer,
    facebook_comment_count integer, 
    ...
    );

If for some reason you need to separate this data from others in the table, create a new secondary table with a foreign key to the main table.

If for some mysterious reason you have to store the data in a single column, use the jsonb type, example:

with pl(id, facebook) as (
values 
    (1, '{"total_count": 14, "comment_count": 0}'::jsonb),
    (2, '{"total_count": null, "comment_count": null}'::jsonb),
    (3, '{"total_count": 7, "comment_count": 10}'::jsonb)
)

select *
from pl 
where (facebook->>'total_count')::integer between 5 and 10

hstore can be an alternative to jsonb.

All these ways are much easier to maintain and much more efficient than your current model. Time to move to the bright side of power.

Sign up to request clarification or add additional context in comments.

3 Comments

I've run the second query and I'm getting an error: ERROR: invalid input syntax for type numeric: ""
Ok I've found that there are some rows like this: {{commentsbox_count,""},{comment_plugin_count,""},{total_count,""},{comment_count,""},{share_count,""},{reaction_count,""}} and I think this is the problem. Any ideas how to fix it? Exclude those rows from query?
Ok I've found a solution: SELECT facebook[1][2] FROM pl WHERE (facebook[1][2] != '') AND (facebook[1][2]::numeric BETWEEN 5 and 10)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.