Why error occurred while creating GIN index? - postgresql

I've created a table to investigate text searching and using GIST and GIN indexes:
CREATE TABLE test
(
id serial NOT NULL,
the_text text,
CONSTRAINT test_pkey PRIMARY KEY (id)
)
And added some random values:
insert into test values (generate_series(1,100000), md5(random()::text))
And wanted to create GIN index:
create index on test using gin(the_text);
But I had an error:
ERROR: data type text has no default operator class for access method "gist"
Could you help me with that?

You need to enable :btree_gin or :btree_gist as well, since it's some sort of dependency for CREATE INDEX to work. The following worked for me and fixed the message ERROR: data type text has no default operator class for access method "gin"
CREATE EXTENSION pg_trgm;
CREATE EXTENSION btree_gin;
CREATE INDEX index_email_gin ON users USING GIN (email);

For full text search use:
CREATE INDEX test_gin_idx ON test USING gin (to_tsvector('english', the_text));
For trigram search you can use pg_trgm extension
CREATE EXTENSION pg_trgm;
CREATE INDEX test_the_text_gin_idx ON test USING GIN (the_text gin_trgm_ops);

Related

jOOQ code generator does not generate corresponding Index if a UNIQUE index has the function defined on the field

I have a unique index as below to achieve case-insensitive unique constraint on the project name
CREATE UNIQUE INDEX IF NOT EXISTS unique_project_name__idx ON project (UPPER(name));
It seems that jOOQ code generator does not generate the corresponding constant in Indexes.java for such UNIQUE index.
However, it works for the index without UPPER() function
CREATE UNIQUE INDEX IF NOT EXISTS unique_project_name__idx ON project (name);
// corresponding generation in Indexes.java
public static Index UNIQUE_PROJECT_NAME__IDX = Internal.createIndex("unique_project_name__idx", Project.PROJECT, new OrderField[] { Project.PROJECT.NAME }, true);
I use jOOQ 3.13.2 and PostgreSQL 11.2.
Any idea?
Is citext a better way for case-insensitive unique constraint?
This is a missing feature in jOOQ 3.13: https://github.com/jOOQ/jOOQ/issues/6310

Built in operator class timestamptz_minmax_ops not supproted for creating index in postgresql

It seems like built in operator class for postgres listed in the offical doc is not supported when creating indexes.
For example the following run into error
CREATE INDEX my_index_name
ON public.my_table USING btree
(my_column timestamptz_minmax_ops)
TABLESPACE pg_default;
while this is ok
CREATE INDEX my_index_name
ON public.my_table USING btree
(my_column timestamptz_ops)
TABLESPACE pg_default;
Even though timestamptz_minmax_ops is listed as the name of the operator class in the doc.
Am I missing something?
The operator class timestamptz_minmax_ops is for the brin access method and not for btree, hence the error.
You can use this operator class only if the index is created USING brin, while your index, lacking a USING clause, uses the default access method btree.
To help you on with your goal: Why do you want timestamptz_minmax_ops? What query should the index speed up?

PostgreSQL: pg_trgm full-text search with jsonb columns?

I have a table with a jsonb column where I store variable data. I would like to search this column and also find fragments (leading or trailing whitespace). I think I know how to do this with text columns but cannot wrap my head around how to achieve this with jsonb columns.
There are two scenarios that I would like to achieve:
Search a specific key inside the jsonb column only (for example
data->>company)
Search the whole jsonb column
For text columns I generate gin indexes using pg_trgm.
Install extension pg_trgm:
CREATE extension if not exists pg_trgm;
Create table & index:
CREATE TABLE tbl (
col_text text,
col_json jsonb
);
CREATE INDEX table_col_trgm_idx ON tbl USING gin (col_text gin_trgm_ops);
Example query:
SELECT * FROM tbl WHERE col_text LIKE '%foo%'; -- leading wildcard
SELECT * FROM tbl WHERE col_text ILIKE '%foo%'; -- works case insensitive as well
Trying the same with the jsonb column fails. If I try to index the whole column
CREATE INDEX table_col_trgm_idx ON tbl USING gin (col_json gin_trgm_ops);
I get the error
ERROR (datatype_mismatch): operator class "gin_trgm_ops" does not accept data type jsonb
(Which makes sense). If I try to index just one key of the jsonb column I also receive an error:
CREATE INDEX table_col_trgm_idx ON tbl USING gin (col_json->>company gin_trgm_ops);
Error:
ERROR (syntax_error): syntax error at or near "->>"
I used this answer by #erwin-brandstetter as a reference. Any help is highly appreciated (and no, I don't want to implement Elasticsearch as of now :) ).
Edit: Creating the index like this actually works:
CREATE INDEX table_col_trgm_idx ON tbl USING gin ((col_json->>'company') gin_trgm_ops);
And querying it also doesn't lead to an error:
SELECT * FROM tbl WHERE col_json->>'company' LIKE '%foo%';
But the result is always empty.

How to create a multicolumn GiST index in Postgresql

The postgresql documentation specifies that a GiST index can have multiple columns, but does not provide an example of what this might look like.
I have a table that tracks assets owned by different customers.
CREATE TABLE asset (
id serial PRIMARY KEY,
description text NOT NULL,
customer_id uuid NOT NULL
);
I'm writing a query that allows a customer to search for an asset based on words in it's description.
SELECT *
FROM asset
WHERE to_tsvector('english', asset.description) ## plainto_tsvector('english', ?)
AND asset.customer_id = ?;
Were this a non-tsvector query, I'd build a simple multicolumn index
CREATE INDEX idx_name ON asset(customer_id, description);
I can create an index only on the tsvector:
CREATE INDEX idx_name ON asset USING gist(to_tsvector('english', asset.description));
However, the query optimizer doesn't use the gist index, because it seems to want to do customer_id filtering first. Is there a way that I can include the non-tsvector field customer_id in the gist index, somehow, or am I out of luck?
You can create a multi column GIN or GiST index in Postrgres using the following:
CREATE INDEX index_name
ON table_name
USING gist (field_one gist_trgm_ops, field_two gist_trgm_ops);

Using postgresql gin or gist index with bigint column

i am trying to create gin index on bigint column and getting an error (PostgreSQL 9.1.9 / Debian 7).
CREATE TABLE test (id bigint CONSTRAINT test_pkey PRIMARY KEY, field bigint);
CREATE INDEX idx_test_field ON test using GIN(field);
ERROR: data type bigint has no default operator class for access method "gin"
HINT: You must specify an operator class for the index or define a default operator class for the data type.
Is there no default support for int8 gin,gist indexes ?
There's generally no reason to create a GiST or GIN index on a primitive type.
If you do require this - say, if you want a composite index that includes both some primitive types and some more complex GiST / GIN-only index types - then you will want the btree_gist or btree_gin modules, as appropriate.
CREATE EXTENSION btree_gin;