如何在续集中逃避`$ like`通配符`%`和`_`?

时间:2017-02-28 22:19:55

标签: javascript sqlite sequelize.js

如何告诉sequelize(使用sqlite3)在%子句中转义通配符(_$like)?

例如,我想生成一个与下面的查询相似的查询,该查询在任何" things.description"中找到文字字符串_cool_。 (不只是单词" cool"被任何字符包围):

SELECT * FROM things WHERE description LIKE '\_cool\_' ESCAPE '\';  

我猜它看起来像这样,但结果查询不是我希望的:

Thing.findAll({
  where: {
    description: {
      $like: ['?', '_cool_'],
      // ... or ...
      $like: '\\_cool\\_',
      $escape: '\\',
    }
  }
});

// => Executing (default):
// SELECT `id`, `description`
//   FROM `Things` AS `Thing`
//   WHERE `Thing`.`description` LIKE '?','_cool_';

不幸的是,我不能放入原始查询,因为" LIKE"子句将成为更大的动态查询的一部分。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

我唯一想到的就是

description: {
    $like: sequelize.literal(`'\\_cool\\_' ESCAPE '\\'`)
}

生成类似

的SQL
LIKE '\_cool\_' ESCAPE '\'

答案 1 :(得分:0)

基于@piotrbienias的完整解决方案,可以接受任何用户输入并正确地逃避它 -

if (typeof query.string !== 'string') {
    throw Error('expecting string')
}
const inputRaw = query.string.replace(/(_|%|\\)/g, '\\$1');
const inputSec = sequelize.escape(`%${inputRaw}%`);
description = {
    $like: sequelize.literal(`${inputSec} ESCAPE '\\'`)
};

对于示例字符串_cool_,这将转换为 -

LIKE '%\\_cool\\_%' ESCAPE '\\'

您可以根据实际用例更改逻辑以添加其他通配符

如果你使用mysql而不是sqlite,那么默认的转义是\所以可以删除ESCAPE声明