Last active
July 25, 2023 21:42
-
-
Save mathisonian/8074838 to your computer and use it in GitHub Desktop.
postgres full text search in sequelize.js. see this blog post for more information http://www.mathisonian.com/weblog/postgres-full-text-search-with-sequelizejs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Sequelize = require('sequelize'); | |
module.exports = function(config) { | |
var models = {}; | |
sequelize = new Sequelize(config.database, config.username, config.password, config.options); | |
// Bootstrap models | |
fs.readdirSync(__dirname).forEach(function (file) { | |
if (~file.indexOf('.js') && file.indexOf('index.js') < 0) { | |
var model = sequelize.import(file); | |
console.log(model.name); | |
models[model.name] = model; | |
} | |
}); | |
sequelize.sync().done(function() { | |
models.Post.addFullTextIndex(); | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
module.exports = function(sequelize, DataTypes) { | |
return sequelize.define('Post', { | |
'title': { type: DataTypes.STRING, required: true }, | |
'content': { type: DataTypes.TEXT, required: true }, | |
'slug': { type: DataTypes.STRING, required: true } | |
}, { | |
classMethods: { | |
getSearchVector: function() { | |
return 'PostText'; | |
}, | |
addFullTextIndex: function() { | |
if(sequelize.options.dialect !== 'postgres') { | |
console.log('Not creating search index, must be using POSTGRES to do this'); | |
return; | |
} | |
var searchFields = ['title', 'content']; | |
var Post = this; | |
var vectorName = Post.getSearchVector(); | |
sequelize | |
.query('ALTER TABLE "' + Post.tableName + '" ADD COLUMN "' + vectorName + '" TSVECTOR') | |
.success(function() { | |
return sequelize | |
.query('UPDATE "' + Post.tableName + '" SET "' + vectorName + '" = to_tsvector(\'english\', ' + searchFields.join(' || \' \' || ') + ')') | |
.error(console.log); | |
}).success(function() { | |
return sequelize | |
.query('CREATE INDEX post_search_idx ON "' + Post.tableName + '" USING gin("' + vectorName + '");') | |
.error(console.log); | |
}).success(function() { | |
return sequelize | |
.query('CREATE TRIGGER post_vector_update BEFORE INSERT OR UPDATE ON "' + Post.tableName + '" FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger("' + vectorName + '", \'pg_catalog.english\', ' + searchFields.join(', ') + ')') | |
.error(console.log); | |
}).error(console.log); | |
}, | |
search: function(query) { | |
if(sequelize.options.dialect !== 'postgres') { | |
console.log('Search is only implemented on POSTGRES database'); | |
return; | |
} | |
var Post = this; | |
query = sequelize.getQueryInterface().escape(query); | |
console.log(query); | |
return sequelize | |
.query('SELECT * FROM "' + Post.tableName + '" WHERE "' + Post.getSearchVector() + '" @@ plainto_tsquery(\'english\', ' + query + ')', Post); | |
} | |
} | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@hobberwickey interesting, you added the tsvector column to migration, what did you add in your model files, I cannot find anything called DataType.TS_VECTOR or DataType.DOCUMENT for Sequelize