В настоящее время я использую функцию поиска в моем приложении rails, используя pg_search для PostgreSQL полнотекстового поиска. К сожалению, у меня проблема с получением миграции, чтобы добавить столбец tsvector, GIN INDEX и TRIGGER в таблицу листингов. Миграция выполняется успешно, но не создает вещи, указанные в файле миграции.
Ошибка при попытке доступа к столбцу tsv:
I, [2020-03-22T10:49:43.273416 #64203] INFO -- : Started GET "/api/v1/public/search?q=Adidas" for ::1 at 2020-03-22 10:49:43 +1000
D, [2020-03-22T10:49:43.367465 #64203] DEBUG -- : (6.1ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
I, [2020-03-22T10:49:43.383171 #64203] INFO -- : Processing by Api::V1::Public::ListingsController#search as */*
I, [2020-03-22T10:49:43.383234 #64203] INFO -- : Parameters: {"q"=>"Adidas"}
D, [2020-03-22T10:49:43.638039 #64203] DEBUG -- : Listing Load (12.4ms) SELECT "listings".* FROM "listings" INNER JOIN (SELECT "listings"."id" AS pg_search_id, (ts_rank(("listings"."tsv"), (to_tsquery('simple', ''' ' || 'Adidas' || ' ''' || ':*')), 0)) AS rank FROM "listings" WHERE (("listings"."tsv") @@ (to_tsquery('simple', ''' ' || 'Adidas' || ' ''' || ':*')))) AS pg_search_8a836f245cd6a84ba9cbd1 ON "listings"."id" = pg_search_8a836f245cd6a84ba9cbd1.pg_search_id ORDER BY pg_search_8a836f245cd6a84ba9cbd1.rank DESC, "listings"."id" ASC LIMIT $1 [["LIMIT", 100]]
D, [2020-03-22T10:49:43.638832 #64203] DEBUG -- : ↳ app/controllers/application_controller.rb:47:in `public_render_listings_helper'
I, [2020-03-22T10:49:43.639121 #64203] INFO -- : Completed 500 Internal Server Error in 256ms (ActiveRecord: 22.8ms | Allocations: 45123)
F, [2020-03-22T10:49:43.640013 #64203] FATAL -- :
ActiveRecord::StatementInvalid (PG::UndefinedColumn: ERROR: column listings.tsv does not exist
LINE 1: ...SELECT "listings"."id" AS pg_search_id, (ts_rank(("listings"...
^
):
Файл миграции:
class AddTsVectorColumns < ActiveRecord::Migration[6.0]
def change
def up
add_column :listings, :tsv, :tsvector
add_index :listings, :tsv, using: 'gin'
execute <<-SQL
CREATE OR REPLACE FUNCTION update_listings_tsv() RETURNS trigger AS $$
BEGIN
new.tsv := (
SELECT
setweight(to_tsvector(l.item_name), 'A') ||
setweight(to_tsvector(coalesce((string_agg(brands.name, ' ')), '')), 'A') ||
setweight(to_tsvector(coalesce((string_agg(colours.name, ' ')), '')), 'B') ||
setweight(to_tsvector(l.description), 'B') ||
setweight(to_tsvector(categories.name), 'B') ||
setweight(to_tsvector(sub_categories.name), 'B') ||
setweight(to_tsvector(sizes.name), 'B') ||
setweight(to_tsvector(users.username), 'C')
FROM listings l
JOIN users ON users.id = l.user_id
JOIN categories ON categories.id = l.category_id
JOIN sub_categories ON sub_categories.id = l.sub_category_id
JOIN sizes ON sizes.id = l.size_id
JOIN conditions ON conditions.id = l.condition_id
-- Associative Tables
JOIN brands_listings ON brands_listings.listing_id = brands_listings.brand_id
JOIN brands ON brands.id = brands_listings.brand_id
JOIN colours_listings ON colours_listings.listing_id = colours_listings.colour_id
JOIN colours ON colours.id = colours_listings.colour_id
WHERE l.id = new.id
GROUP BY l.id, users.id, categories.id, sub_categories.id, sizes.id, conditions.id
);
RETURN new;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE
ON listings FOR EACH ROW EXECUTE PROCEDURE update_listings_tsv();
SQL
end
def down
execute <<-SQL
DROP TRIGGER tsvectorupdate
ON listings
SQL
remove_index :listings, :tsv
remove_column :listings, :tsv
end
end
end
Вывод миграции:
D, [2020-03-22T13:23:39.965602 #70710] DEBUG -- : primary::SchemaMigration Create (0.4ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20200313140854"]]
D, [2020-03-22T13:23:39.968646 #70710] DEBUG -- : (0.9ms) COMMIT
I, [2020-03-22T13:23:39.969992 #70710] INFO -- : Migrating to AddTsVectorColumns (20200321060306)
== 20200321060306 AddTsVectorColumns: migrating ===============================
== 20200321060306 AddTsVectorColumns: migrated (0.0000s) ======================
D, [2020-03-22T13:23:39.973220 #70710] DEBUG -- : (0.4ms) BEGIN
D, [2020-03-22T13:23:39.975042 #70710] DEBUG -- : primary::SchemaMigration Create (0.4ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version" [["version", "20200321060306"]]
D, [2020-03-22T13:23:39.977113 #70710] DEBUG -- : (0.4ms) COMMIT
D, [2020-03-22T13:23:39.986874 #70710] DEBUG -- : ActiveRecord::InternalMetadata Load (0.8ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 LIMIT $2 [["key", "environment"], ["LIMIT", 1]]
D, [2020-03-22T13:23:39.993805 #70710] DEBUG -- : (0.2ms) BEGIN
D, [2020-03-22T13:23:39.999419 #70710] DEBUG -- : ActiveRecord::InternalMetadata Create (4.2ms) INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "key" [["key", "environment"], ["value", "development"], ["created_at", "2020-03-22 03:23:39.992922"], ["updated_at", "2020-03-22 03:23:39.992922"]]
D, [2020-03-22T13:23:40.002363 #70710] DEBUG -- : (0.7ms) COMMIT
D, [2020-03-22T13:23:40.003788 #70710] DEBUG -- : (0.4ms) SELECT pg_advisory_unlock(6123583507257778380)
D, [2020-03-22T13:23:40.258046 #70710] DEBUG -- : (0.6ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
Модель листинга (где используется столбец tsv):
class Listing < ApplicationRecord
include PgSearch::Model
pg_search_scope(
:search,
against: [],
using: {
tsearch: {
tsvector_column: 'tsv',
any_word: true,
prefix: true,
negation: true,
dictionary: 'simple'
}
}
)
end
Извлечение из схемы sql (с config.active_record.schema_format =: sql) - - PostgreSQL дамп базы данных -
SET statement_timeout = 0;
SET lock_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET row_security = off;
--
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: -
--
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
--
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: -
--
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
SET search_path = public, pg_catalog;
SET default_tablespace = '';
SET default_with_oids = false;
--
-- Name: listings; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE listings (
id bigint NOT NULL,
item_name character varying,
description character varying,
price integer,
shipping_cost integer,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
category_id bigint,
sub_category_id bigint,
size_id bigint,
user_id bigint,
full_item_name text,
cached_votes_total integer DEFAULT 0,
cached_votes_score integer DEFAULT 0,
cached_votes_up integer DEFAULT 0,
cached_votes_down integer DEFAULT 0,
cached_weighted_score integer DEFAULT 0,
cached_weighted_total integer DEFAULT 0,
cached_weighted_average double precision DEFAULT 0.0,
flaremeter integer DEFAULT 0,
condition_id bigint,
cover_photo_data text
);
--
-- Name: listings_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE listings_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: listings_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE listings_id_seq OWNED BY listings.id;
--
-- PostgreSQL database dump complete
--
SET search_path TO "$user", public;
INSERT INTO "schema_migrations" (version) VALUES
('20200223103428'),
('20200313111818'),
('20200313140854'),
('20200321060306');