3

I'm using the Sequelize ORM in NodeJS to manage a postgreSQL database. I'm using the JSONB datatype in my table, I need an index on the JSONB field and an unique constraint on a property of this JSON. If I have to do in a classic SQL here my script :

CREATE TABLE tableJson (id SERIAL PRIMARY KEY,
                        content JSONB NOT NULL);
CREATE INDEX j_idx ON tableJson USING gin(content jsonb_path_ops);
CREATE UNIQUE INDEX content_name_idx ON tableJson(((content->>'name')::varchar));

I've found how to create the table with the INDEX but not how to deal with the UNIQUE constraint. Here is a sample of my script :

var tableJson = sequelize.define('tableJson', {
    content: Sequelize.JSONB
}, {
    indexes: [{
        fields: ['content'],
        using: 'gin',
        operator: 'jsonb_path_ops'
    }
});

Is there a solution for my problem? If not I'll probably use the sequelize.query method to execute raw query but this is not very evolutive.

Any help would be appreciated!

2 Answers 2

0

This is the workaround I use to add indexes on JSONB fields with Postgres and Sequelize.

First, set the quoteIdentifiers option to false in your Sequelize client.

const seq = new Sequelize(db, user, pass, {
    host: host,
    dialect: 'postgres',
    quoteIdentifiers: false,
});

(Watch out though, this will make all your table names case insensitive when created by Sequelize.sync())

You can now add indexes on JSONB fields this way in your model definition :

indexes: [
    {
        fields: ['content'],
        using: 'gin',
        operator: 'jsonb_path_ops'
    },
    {
        fields: ['((content->>\'name\')::varchar)'],
        unique: true,
        name: 'content_name_idx',
    }
],
Sign up to request clarification or add additional context in comments.

Comments

0

You have to do two things.

  1. Set quoteIdentifiers to false.
  2. set unique to true in indexes.

Here is the complete code

const seq = new Sequelize(db, user, pass, {
host: host,
  dialect: 'postgres',
  quoteIdentifiers: false,
});

const User = seq.define('User', {
  name: {
    type: Sequelize.STRING,
  },
  content: {
    type: Sequelize.JSONB,
  },
}, {
  indexes: [
    {
      fields: ['content'],
      using: 'gin',
      operator: 'jsonb_path_ops',
    },
    {
      fields: ['((content->>"name")::varchar)'],
      unique: true,
      name: 'content_name_idx',
    },
  ],
});

Comments

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.