全文索引是一种常见的搜索技术,通过对文本内容建立索引并提供高效的搜索功能,使得用户可以快速地找到自己感兴趣的内容。在前端开发中,我们经常需要使用全文索引来实现搜索功能,而 Sequelize 是一种非常流行的 Node.js ORM 框架,提供了丰富的数据库操作功能,其中包括全文索引的实现。
什么是全文索引?
全文索引是一种建立在文本内容上的索引方式,与传统的索引只关注特定字段或属性不同。全文索引会对文本内容中的每一个单词或短语建立索引,使得用户可以通过搜索词中的任意一个单词或短语,快速地找到与之相关的文本内容。
在 Sequelize 中实现全文索引是非常简单的,只需要在定义模型时添加对应的字段即可。Sequelize 提供了三种不同类型的全文索引:
- 完全匹配搜索
完全匹配搜索是最简单的全文索引方式,适用于对文本内容进行精确匹配的搜索。在 Sequelize 中,可以通过给字段添加 Sequelize.TEXT 属性,来实现完全匹配搜索的全文索引。例如:
const Post = sequelize.define('post', {
title: Sequelize.TEXT, // 标题字段
content: Sequelize.TEXT // 内容字段
});定义了这样的模型之后,就可以通过 Op.like 运算符来实现完全匹配搜索:
const posts = await Post.findAll({
where: {
[Op.or]: [
{ title: { [Op.like]: '%keyword%' } },
{ content: { [Op.like]: '%keyword%' } }
]
}
});这样就可以搜索出所有标题或内容中包含关键词的文章。
- 短语搜索
短语搜索是一种更加灵活的全文索引方式,可以支持搜索包含特定短语的文本内容。在 Sequelize 中,可以通过给字段添加 Sequelize.TSVECTOR 属性,来实现短语搜索的全文索引。例如:
// www.javascriptcn.com code example
const Post = sequelize.define('post', {
title: Sequelize.TSVECTOR, // 标题字段
content: Sequelize.TSVECTOR // 内容字段
}, {
indexes: [
{
name: 'post_search_index',
using: 'gin', // 使用 gin 索引
fields: ['title', 'content']
}
]
});需要注意的是,短语搜索需要使用 PostgreSQL 的全文搜索插件,因此需要在数据库中手动安装相应的插件。同时,需要在模型定义中添加 indexes 属性,并指定对应的索引名称、类型和字段。
定义了这样的模型之后,需要使用 sequelize.literal 方法来定义搜索条件:
const posts = await Post.findAll({
where: sequelize.literal(
`to_tsvector('english', title || ' ' || content) @@ plainto_tsquery('english', '${keyword}')`
)
});在 sequelize.literal 方法中,需要使用 PostgreSQL 的全文搜索函数 to_tsvector 将 title 和 content 合并成一个整体,使用 plainto_tsquery 函数将搜索关键词转化为适合全文搜索的格式。最后使用 @@ 运算符来判断搜索内容是否匹配。
- 全文搜索
全文搜索是最灵活的全文索引方式,可以匹配文本内容中的任意单词或短语。在 Sequelize 中,可以通过给字段添加 Sequelize.TSVECTOR 属性,并使用完全匹配搜索的方式来实现全文搜索。例如:
// www.javascriptcn.com code example
const Post = sequelize.define('post', {
title: {
type: Sequelize.TEXT,
allowNull: false,
set(val) {
this.setDataValue('title', val);
this.setDataValue('title_vector', sequelize.literal(
`to_tsvector('english', '${val}')`
));
}
},
title_vector: Sequelize.TSVECTOR // 标题向量
}, {
indexes: [
{
name: 'post_search_index',
using: 'gin', // 使用 gin 索引
fields: ['title_vector']
}
]
});在定义模型时,除了添加 Sequelize.TSVECTOR 属性之外,还需要添加一个同名的虚拟字段 title_vector,用来存储实际的全文索引数据。同时,在定义 title 字段的 set 方法中,需要使用 setDataValue 方法将正常的 title 值和全文索引值 title_vector 分别设置。
定义了这样的模型之后,就可以使用 sequelize.literal 方法来实现全文搜索:
const posts = await Post.findAll({
where: sequelize.literal(
`title_vector @@ to_tsquery('english', '${keyword}')`
)
});在 sequelize.literal 方法中,需要使用 to_tsquery 函数将搜索关键词转化为适合全文搜索的格式,并使用 @@ 运算符来判断搜索内容是否匹配。
示例代码
以下是一个完整的示例代码,展示了如何在 Sequelize 中使用全文索引实现文章搜索功能:
// www.javascriptcn.com code example
const { Sequelize, Op } = require('sequelize');
const sequelize = new Sequelize('database', 'username', 'password', {
host: 'localhost',
dialect: 'postgres',
logging: false
});
const Post = sequelize.define('post', {
title: Sequelize.TSVECTOR,
content: Sequelize.TSVECTOR
}, {
indexes: [
{
name: 'post_search_index',
using: 'gin',
fields: ['title', 'content']
}
]
});
const setupDatabase = async () => {
await sequelize.sync();
await Post.bulkCreate([
{
title: 'Hello world',
content: 'This is my first post'
},
{
title: 'Sequelize tutorial',
content: 'Learn how to use Sequelize in Node.js'
},
{
title: 'Node.js search example',
content: 'A demo of using full-text search in Node.js'
}
]);
};
const searchPosts = async (keyword) => {
const posts = await Post.findAll({
where: sequelize.literal(
`to_tsvector('english', title || ' ' || content) @@ plainto_tsquery('english', '${keyword}')`
)
});
return posts;
};
setupDatabase().then(() => {
searchPosts('node.js').then((posts) => {
console.log(posts);
sequelize.close();
});
});通过这个示例代码,我们可以看到如何在 Sequelize 中定义模型,并使用全文索引来实现文章的搜索功能。通过灵活地使用不同类型的全文索引,我们可以让搜索功能更加智能和便捷,提高用户的使用体验。
总结
Sequelize 是一种非常流行的 Node.js ORM 框架,提供了丰富的数据库操作功能,其中包括全文索引的实现。通过熟练掌握 Sequelize 中的全文索引实现方法,我们可以轻松地实现高效、智能的文章搜索功能,为用户提供更好的使用体验。
Source: FunTeaLearn,Please indicate the source for reprints https://funteas.com/post/6457c7d1968c7c53b0a6140d