Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unaccent in Sequelize

I'm currently working in a project that uses ExpressJS, PostgreSQL and Sequelize as the ORM. I developed a search function that makes a query that searches items by name:

models.foo.findAll({
  where: {
    $or: [
      {name: {$ilike: keywords}},
      {searchMatches: {$contains: [keywords]}}
    ]
  },
  order: [['name', 'ASC']]
})

This works fine, but if the name contains an special character (like á, é, í, ó or ú) this query won't find it.

Is there a way to make the query search names with speacial characters in a meaningful sense? Like if I search the name "potato" the results "The potato", "Da potátos" and "We are the pótatóes" will come out, but not "We eat pátatos" (since á != o)

like image 292
Potray Avatar asked Jan 03 '23 16:01

Potray


2 Answers

This can now be done without a completely RAW query, but using Sequelize's in built functions:

models.foo.findAll({
  where: Sequelize.where(
    Sequelize.fn('unaccent', Sequelize.col('name')), {
        [Op.iLike]:`%${keywords}%`
  }),
  order: [['name', 'ASC']]
})

Then ordering, associations etc. all work still as normal :).

like image 81
Jamie Avatar answered Jan 13 '23 09:01

Jamie


I finally found a valid solution. First I created the unaccent extension:

create extension unaccent;

Then I just used a raw query (I couldn't figure out how to build the query using Sequelize's way) like this:

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})

And it works!

like image 31
Potray Avatar answered Jan 13 '23 09:01

Potray