-- +goose Up CREATE TYPE recipe_source AS ENUM ('spoonacular', 'ai', 'user'); CREATE TYPE recipe_difficulty AS ENUM ('easy', 'medium', 'hard'); CREATE TABLE recipes ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), source recipe_source NOT NULL DEFAULT 'spoonacular', spoonacular_id INTEGER UNIQUE, title VARCHAR(500) NOT NULL, description TEXT, title_ru VARCHAR(500), description_ru TEXT, cuisine VARCHAR(100), difficulty recipe_difficulty, prep_time_min INTEGER, cook_time_min INTEGER, servings SMALLINT, image_url TEXT, calories_per_serving DECIMAL(8, 2), protein_per_serving DECIMAL(8, 2), fat_per_serving DECIMAL(8, 2), carbs_per_serving DECIMAL(8, 2), fiber_per_serving DECIMAL(8, 2), ingredients JSONB NOT NULL DEFAULT '[]'::jsonb, steps JSONB NOT NULL DEFAULT '[]'::jsonb, tags JSONB NOT NULL DEFAULT '[]'::jsonb, avg_rating DECIMAL(3, 2) NOT NULL DEFAULT 0.0, review_count INTEGER NOT NULL DEFAULT 0, created_by UUID REFERENCES users (id) ON DELETE SET NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX idx_recipes_title_fts ON recipes USING GIN (to_tsvector('simple', coalesce(title_ru, '') || ' ' || coalesce(title, ''))); CREATE INDEX idx_recipes_ingredients ON recipes USING GIN (ingredients); CREATE INDEX idx_recipes_tags ON recipes USING GIN (tags); CREATE INDEX idx_recipes_cuisine ON recipes (cuisine); CREATE INDEX idx_recipes_difficulty ON recipes (difficulty); CREATE INDEX idx_recipes_prep_time ON recipes (prep_time_min); CREATE INDEX idx_recipes_calories ON recipes (calories_per_serving); CREATE INDEX idx_recipes_source ON recipes (source); CREATE INDEX idx_recipes_rating ON recipes (avg_rating DESC); -- +goose Down DROP TABLE IF EXISTS recipes; DROP TYPE IF EXISTS recipe_difficulty; DROP TYPE IF EXISTS recipe_source;