postgresql 如何使用Knex.js添加GIN索引

ktecyv1j  于 2023-06-05  发布在  PostgreSQL
关注(0)|答案(4)|浏览(479)

我一直在尝试使用Knex.js在我的表中的一列上添加GIN索引,但我无法实现这一点。我正试着做这样的事-

exports.up = function(knex, Promise) {
    return knex.schema.createTable('prediction_models', function(table){
            table.increments('id');
            table.string('model_name').index();
            table.jsonb('model_params');
            table.timestamp('createdAt').defaultTo(knex.fn.now());
        })
        .then(createGinIndex());

    function createGinIndex() {
        return knex.raw('CREATE INDEX modelgin ON public.prediction_models USING GIN (model_params);');
    }
};

exports.down = function(knex, Promise) {
    return knex.schema.dropTable('prediction_models');
};

我使用PostgreSQL数据库。有没有人能告诉我,这是正确的方法来实现这一点?如果是,我的代码有什么问题,如果不是,如何实现它?谢谢!

jdzmm42g

jdzmm42g1#

那些寻找更“knexy”解决这个问题的人:不需要像Mikael Lepistö的解决方案那样使用.raw.index可链接接受名为indexType的第二个参数。它可以这样使用:

knex.schema.createTable('table_name', table => {
  table.jsonb('column_name').index(null, 'GIN')
})

(the null在第一个参数上是我说“为我命名这个索引”)
这段代码将生成以下查询:

create table "table_name" ("column_name" jsonb);
create index "table_name_column_name_index" on "table_name" using GIN ("column_name")

目前我正在创建这样一个索引,但是出于性能考虑,我希望它只支持jsonb_path_ops操作符类(按照section 8.14.4 of the documentation)。这需要create index语句以using GIN ("column_name" jsonb_path_ops)结尾。因此,我需要使用raw,但有很多用例.index就足够了。

hs1rzwqc

hs1rzwqc2#

你应该可以创建完整的GIN索引,如下所示:

CREATE INDEX on prediction_models USING GIN (model_params)

有关为jsonb列创建索引的更多信息,请参见https://www.vincit.fi/en/blog/objection-js-postgresql-power-json-queries/的末尾
您可以打印出迁移运行的查询,如下所示(http://runkit.com/embed/8fm3z9xzjz9b):

var knex = require("knex")({ client: 'pg' });
const queries = knex.schema.createTable('prediction_models', function (table){
    table.increments('id');
    table.string('model_name').index();
    table.jsonb('model_params');
    table.timestamp('createdAt').defaultTo(knex.fn.now());
}).raw('CREATE INDEX on prediction_models USING GIN (model_params)')
.toSQL();

queries.forEach(toSql => console.log(toSql.sql));

并将它们复制粘贴到psql:

mikaelle=# begin;
BEGIN
mikaelle=# create table "prediction_models" ("id" serial primary key, "model_name" varchar(255), "model_params" jsonb, "createdAt" timestamptz default CURRENT_TIMESTAMP);
CREATE TABLE
mikaelle=# create index "prediction_models_model_name_index" on "prediction_models" ("model_name");
CREATE INDEX
mikaelle=# CREATE INDEX on prediction_models USING GIN (model_params);
CREATE INDEX
mikaelle=# commit;
COMMIT
mikaelle=#
mikaelle=# \d prediction_models
                                     Table "public.prediction_models"
    Column    |           Type           |                           Modifiers                            
--------------+--------------------------+----------------------------------------------------------------
 id           | integer                  | not null default nextval('prediction_models_id_seq'::regclass)
 model_name   | character varying(255)   | 
 model_params | jsonb                    | 
 createdAt    | timestamp with time zone | default now()
Indexes:
    "prediction_models_pkey" PRIMARY KEY, btree (id)
    "prediction_models_model_name_index" btree (model_name)
    "prediction_models_model_params_idx" gin (model_params)

mikaelle=#
iugsix8n

iugsix8n3#

exports.up = function (knex) {
    const raw = `
    CREATE EXTENSION btree_gin;
    ALTER TABLE employee
    ADD COLUMN employee_index tsvector; 
    UPDATE employee
    SET employee_index = to_tsvector(firstname || ' ' || lastname);
    CREATE INDEX employee_index_gin
    ON employee
    USING GIN (employee_index);
    `

    return knex.schema.raw(raw)
};

exports.down = function (knex) {
    const raw = `
    DROP INDEX employee_index_gin;
    ALTER TABLE employee
    DROP COLUMN employee_index;
    DROP EXTENSION btree_gin;
    `

    return knex.schema.raw(raw)
};

在我的usecase中使用的是生的

iovurdzv

iovurdzv4#

GIN索引不能应用于字符串数据类型,但可以应用于数组和JSON数据类型。

return knex.schema.table('test_table',(table)=>{
  table.index(['column_name'], 'idx_index_name','GIN');
});

如果我们想应用内置的操作符类,如array_ops、jsonb_ops、jsonb_path_ops等。我们可以像下面的例子索引:

return knex.schema.table('test_table',(table)=>{
  table.index([knex.raw(`(column_name) jsonb_path_ops`)], 'idx_index_name','GIN')
})

假设,表users包含jsonb中的address列,我们想索引address.permanent_address,那么我们可以通过以下方式实现索引:

return knex.schema.table('users',(table)=>{
  table.index([knex.raw(`(address->'permanent_address') jsonb_path_ops`)], 'idx_index_name','GIN')
})

相关问题