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

问题描述:

我一直试图添加一个GIN索引使用Knex.js在我的表中的一列,但我无法实现这一点。我试图做这样的事情 -如何使用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数据库。任何人都可以告诉我,如果这是实现这个的正确方法?如果是,我的代码有什么问题,如果不是如何实现呢?谢谢!

您应该能够创建完整的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=# 
+0

感谢您的回复。我使用的是与你所建议的相同的查询,但由于某种原因,我无法在同一个迁移中创建索引,我试图创建一个表(注:我试图在创建表后创建一个索引)。所以我创建了两个单独的迁移(创建表,创建索引),这很好运作 –

+0

@HarshalGangurde,这真的很奇怪......我确实通过https://runkit.com/embed/8fm3z9xzjz9b呈现了查询,并且在psql里面运行了它们一个交易,像knex运行它们,一切正常。我会更新答案。 –

那些正在寻找更多的“双膝”解决方案来解决这个问题:没有必要像MikaelLepistö的解决方案那样使用.raw。可链接的.index接受称为indexType的第二个参数。它可用于像这样:

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

(第一个参数的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)。这需要以using GIN ("column_name" jsonb_path_ops)结尾的create index声明。因此,我需要使用原始码,但有大量的使用案例.index就足够了。