【问题标题】:How to add GIN index using Knex.js如何使用 Knex.js 添加 GIN 索引
【发布时间】:2018-02-02 22:02:05
【问题描述】:

我一直在尝试使用 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 数据库。谁能告诉我这是否是实现这一点的正确方法?如果是,我的代码有什么问题,如果不是,如何实现?谢谢!

【问题讨论】:

    标签: javascript node.js postgresql knex.js


    【解决方案1】:

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

    【讨论】:

    • 感谢您的回复。我正在使用与您建议的相同的查询,但由于某种原因,我无法在尝试创建表的同一迁移中创建索引(注意:我试图在创建表后创建索引)。所以我创建了两个单独的迁移(创建表,创建索引),效果很好
    • @HarshalGangurde 真的很奇怪...我确实使用runkit.com/embed/8fm3z9xzjz9b 渲染了查询,并在事务中的 psql 中运行了它们,就像 knex 运行它们并且一切正常。我会更新答案。
    【解决方案2】:

    那些为这个问题寻找更“灵活”的解决方案的人:没有必要像 Mikael Lepistö 的解决方案那样使用 .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 语句。因此,我需要使用 raw,但在很多用例中 .index 就足够了。

    【讨论】:

      【解决方案3】:
      
      
      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)
      };
      
      

      在我的用例中使用 raw

      【讨论】:

        猜你喜欢
        • 2016-08-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-24
        • 2021-11-29
        • 1970-01-01
        • 2018-08-16
        • 2015-09-02
        相关资源
        最近更新 更多