PirateApp
PirateApp

Reputation: 6230

How to create this tsvector generated always as column with sequelize?

I see that sequelize has DataTypes.TSVECTOR for postgres dialect. I have a column whose definition in raw SQL is as follows

tsvector GENERATED ALWAYS AS (((
setweight(to_tsvector('english'::regconfig, (COALESCE(title, ''::character varying))::text), 'A'::"char") || 
setweight(to_tsvector('english'::regconfig, COALESCE(summary, ''::text)), 'B'::"char")) || 
setweight(to_tsvector('english'::regconfig, (COALESCE(content, ''::character varying))::text), 'C'::"char"))) 
STORED

How can I define this in my sequelize model

  const FeedItem = sequelize.define(
    'FeedItem', {
        feedItemId: {
            type: DataTypes.UUID,
            primaryKey: true,
            allowNull: false,
            defaultValue: DataTypes.UUIDV4,
        },
        pubdate: {
            type: DataTypes.DATE,
            allowNull: false,
            defaultValue: sequelize.literal('CURRENT_TIMESTAMP'),
            validate: {
                isDate: true,
            },
        },
        link: {
            type: DataTypes.STRING,
            allowNull: false,
            validate: {
                len: [0, 2047],
            },
        },
        guid: {
            type: DataTypes.STRING,
            validate: {
                len: [0, 2047],
            },
        },
        title: {
            type: DataTypes.TEXT,
            allowNull: false,
            validate: {
                len: [0, 65535],
            },
        },
        summary: {
            type: DataTypes.TEXT,
            validate: {
                len: [0, 65535],
            },
        },
        content: {
            type: DataTypes.TEXT,
            validate: {
                len: [0, 1048575],
            },
        },
        author: {
            type: DataTypes.STRING,
            validate: {
                len: [0, 63],
            },
        },
        tags: {
            type: DataTypes.ARRAY(DataTypes.STRING),
            defaultValue: [],
        },
        // How to do that generated always part here???
        searchable: {
            type: DataTypes.TSVECTOR
        },
    }, {
        timestamps: false,
        underscored: true,
        indexes: [
            {
                name: 'idx_feed_items_searchable',
                fields: ['searchable'],
                using: 'gin',
            },
        ],
    }
  );

Upvotes: 3

Views: 1239

Answers (1)

PirateApp
PirateApp

Reputation: 6230

The model needs to be modified as follows to get this working

  const FeedItem = sequelize.define(
    'FeedItem',
    {
      feedItemId: {
        type: DataTypes.UUID,
        primaryKey: true,
        allowNull: false,
        defaultValue: DataTypes.UUIDV4,
      },
      pubdate: {
        type: DataTypes.DATE,
        allowNull: false,
        defaultValue: sequelize.literal('CURRENT_TIMESTAMP'),
        validate: {
          isDate: true,
        },
      },
      link: {
        type: DataTypes.STRING,
        allowNull: false,
        validate: {
          len: [0, 2047],
        },
      },
      guid: {
        type: DataTypes.STRING,
        validate: {
          len: [0, 2047],
        },
      },
      title: {
        type: DataTypes.TEXT,
        allowNull: false,
        validate: {
          len: [0, 65535],
        },
      },
      summary: {
        type: DataTypes.TEXT,
        validate: {
          len: [0, 65535],
        },
      },
      content: {
        type: DataTypes.TEXT,
        validate: {
          len: [0, 1048575],
        },
      },
      author: {
        type: DataTypes.STRING,
        validate: {
          len: [0, 63],
        },
      },
      tags: {
        type: DataTypes.ARRAY(DataTypes.STRING),
        defaultValue: [],
      },
      // https://stackoverflow.com/questions/67051281/use-postgres-generated-columns-in-sequelize-model
      searchable: {
        type: `tsvector GENERATED ALWAYS AS (((setweight(to_tsvector('english'::regconfig, (COALESCE(title, ''::character varying))::text), 'A'::"char") || setweight(to_tsvector('english'::regconfig, COALESCE(summary, ''::text)), 'B'::"char")) || setweight(to_tsvector('english'::regconfig, (COALESCE(content, ''::character varying))::text), 'C'::"char"))) STORED`,
        set() {
          throw new Error('generatedValue is read-only');
        },
      },
    },
    {
      timestamps: false,
      underscored: true,
      indexes: [
        {
          name: 'idx_feed_items_pubdate_feed_item_id_desc',
          fields: [
            { attribute: 'pubdate', order: 'DESC' },
            { attribute: 'feed_item_id', order: 'DESC' },
          ],
        },
        {
          name: 'idx_feed_items_tags',
          fields: ['tags'],
          using: 'gin',
        },
        {
          name: 'idx_feed_items_searchable',
          fields: ['searchable'],
          using: 'gin',
        },
      ],
    }
  );

Does not work with sequelize.sync({alter: true}) you have to force:true or sequelize migrations

Upvotes: 3

Related Questions