我目前正在使用ExpressJS,PostgreSQL和Sequelize作为ORM的项目。我开发了一个搜索功能,它使查询按名称搜索项目:
models.foo.findAll({
where: {
$or: [
{name: {$ilike: keywords}},
{searchMatches: {$contains: [keywords]}}
]
},
order: [['name', 'ASC']]
})
这样可以正常工作,但如果名称包含特殊字符(如á,é,í,ó或ú),则此查询将无法找到它。
有没有办法让查询搜索名称具有有意义的特殊字符?就像我搜索“马铃薯”这个名字一样,结果“土豆”,“Dapotátos”和“我们是pótatóes”会出来,但不是“我们吃pátatos”(因为á!= o)
答案 0 :(得分:2)
我终于找到了一个有效的解决方案。首先我创建了unaccent扩展:
create extension unaccent;
然后我只使用了一个原始查询(我无法弄清楚如何使用Sequelize的方式构建查询),如下所示:
models.sequelize.query(
`SELECT
*
FROM
"Foos"
WHERE
unaccent("name") ilike unaccent('${keywords}')
OR "searchMatches" @> ARRAY[unaccent('${keywords}')]::VARCHAR(255)[]
ORDER BY
"name" ASC`, {model: models.Foo})
它有效!
答案 1 :(得分:1)
现在可以在没有完全RAW查询的情况下完成,但在内置函数中使用Sequelize:
models.foo.findAll({
where: Sequelize.where(
Sequelize.fn('unaccent', Sequelize.col('name')), {
[Op.iLike]:`%${keywords}%`
}),
order: [['name', 'ASC']]
})
然后排序,关联等所有工作仍然正常:)。
答案 2 :(得分:0)
字典可能就是你要找的东西。基本上可以用来映射同义词并从索引中排除常见元素(例如" a"""来自英文文本)等等。
https://www.postgresql.org/docs/current/static/textsearch-dictionaries.html
答案 3 :(得分:0)
在我的情况下,我使用Sequelize.literal和COLLATE解决了这个问题:
where: Sequelize.literal(`name COLLATE Latin1_general_CI_AI like '%${keywords}%' COLLATE Latin1_general_CI_AI`)
那样,消除两侧的口音。