feat(F-048): completed feature

This commit is contained in:
chattie
2026-08-19 07:17:14 +02:00
parent 8ee1938af9
commit 835ab66eda
187 changed files with 12361 additions and 1065 deletions

View File

@@ -1,83 +1,44 @@
/**
* Migration 026: Fuzzy search with trigram similarity (pg_trgm)
* Migration 026: Fuzzy search with trigram similarity (pg_trgm).
*
* - Enables pg_trgm extension for Levenshtein-like fuzzy matching
* - Creates GIN indexes on product name/description for fast trigram similarity
* - Adds similarity index on brands and categories for term suggestions
*
* Run: node migrations/026_fuzzy_search.js
* This is an ordered node-pg-migrate migration. It must not open its own
* connection or execute work while the migration module is being loaded.
*/
const { Pool } = require('pg');
/** @param {import('node-pg-migrate').MigrationBuilder} pgm */
exports.up = (pgm) => {
pgm.sql('CREATE EXTENSION IF NOT EXISTS pg_trgm');
const pool = new Pool({
connectionString: process.env.DATABASE_URL || 'postgres://mdv:mdv_dev_only@localhost:5432/mercadodevida',
});
pgm.sql(`
CREATE INDEX IF NOT EXISTS catalog_products_name_trgm_idx
ON catalog_products
USING GIN (name gin_trgm_ops)
`);
async function migrate() {
const client = await pool.connect();
pgm.sql(`
CREATE INDEX IF NOT EXISTS catalog_products_description_trgm_idx
ON catalog_products
USING GIN (description gin_trgm_ops)
`);
try {
await client.query('BEGIN');
pgm.sql(`
CREATE INDEX IF NOT EXISTS brands_brands_name_trgm_idx
ON brands_brands
USING GIN (name gin_trgm_ops)
`);
// 1. Enable pg_trgm extension
await client.query(`
CREATE EXTENSION IF NOT EXISTS pg_trgm;
`);
console.log('✓ pg_trgm extension enabled');
pgm.sql(`
CREATE INDEX IF NOT EXISTS categories_categories_name_trgm_idx
ON categories_categories
USING GIN (name gin_trgm_ops)
`);
};
// 2. GIN index on product name for trigram similarity
await client.query(`
CREATE INDEX IF NOT EXISTS catalog_products_name_trgm_idx
ON catalog_products
USING GIN (name gin_trgm_ops);
`);
console.log('✓ catalog_products name trigram index');
// 3. GIN index on product description
await client.query(`
CREATE INDEX IF NOT EXISTS catalog_products_description_trgm_idx
ON catalog_products
USING GIN (description gin_trgm_ops);
`);
console.log('✓ catalog_products description trigram index');
// 4. GIN index on brand names (for suggestions)
await client.query(`
CREATE INDEX IF NOT EXISTS brands_brands_name_trgm_idx
ON brands_brands
USING GIN (name gin_trgm_ops);
`);
console.log('✓ brands_brands name trigram index');
// 5. GIN index on category names (for suggestions)
await client.query(`
CREATE INDEX IF NOT EXISTS categories_categories_name_trgm_idx
ON categories_categories
USING GIN (name gin_trgm_ops);
`);
console.log('✓ categories_categories name trigram index');
// 6. Record migration
await client.query(`
INSERT INTO pgmigrations (name, run_on)
VALUES ('026_fuzzy_search', NOW())
ON CONFLICT (name) DO NOTHING;
`);
console.log('✓ Migration recorded');
await client.query('COMMIT');
console.log('\n✅ Migration 026 complete: fuzzy search indexes created');
} catch (err) {
await client.query('ROLLBACK');
throw err;
} finally {
client.release();
await pool.end();
}
}
migrate().catch((err) => {
console.error('❌ Migration failed:', err.message);
process.exit(1);
});
/** @param {import('node-pg-migrate').MigrationBuilder} pgm */
exports.down = (pgm) => {
pgm.sql('DROP INDEX IF EXISTS categories_categories_name_trgm_idx');
pgm.sql('DROP INDEX IF EXISTS brands_brands_name_trgm_idx');
pgm.sql('DROP INDEX IF EXISTS catalog_products_description_trgm_idx');
pgm.sql('DROP INDEX IF EXISTS catalog_products_name_trgm_idx');
pgm.sql('DROP EXTENSION IF EXISTS pg_trgm');
};