书架:查询生成器:如何对 json 列使用 like 运算符?

Bookshelf: query builder: how to use like operator with json column?

我正在使用 bookshelf 和 postgresql 数据库

信息是 json.

类型的列

我想检索所有类似于“%pattern%”的列 对于 sql 查询,我使用

select * from table where information::text like '%pattern%';

我想用书架查询生成器来做到这一点

model.query(function(qb) {
  qb.where('information', 'LIKE', '%pattern%')
}).fetch()

但它没有用,我在 bookshelf docs

中找不到如何做

有什么想法吗?

这里棘手的部分是,虽然您可能认为 JSON(和 JSONB)列是文本,但它们不是!所以没有办法对一个进行 LIKE 比较。嗯,有,但你必须先将它转换为字符串:

SELECT * FROM wombats WHERE information #>> '{}' LIKE '%pattern%';

这是一个非常糟糕的想法,请不要那样做!正如 @GMB 在评论中指出的那样,JSON 是一种功能更强大的结构化格式。 Postgres 擅长处理 JSON,所以只要向它询问你需要什么。假设您的值在名为 description:

的 JSON 属性 中
SELECT * FROM wombats
  WHERE (information->'description')::TEXT
  LIKE '%pattern%';

在这里,即使我们已经在 JSON 对象中识别出正确的 属性,它的输出类型为 JSON:我们仍然必须将其转换为 ::TEXT,然后使用 LIKE 将其与字符串进行比较。所有这些的 Bookshelf/Knex 版本看起来像:

model
  .query(function(qb) {
    const keyword = "pattern";
    qb.whereRaw(`(information->'description')::TEXT LIKE '%${keyword}%'`)
  })
  .fetch();

显然这部分原始查询不能参数化(至少在 Postgres 中)所以需要 JavaScript 中的字符串替换。这意味着您应该格外小心该字符串的来源(即仅使用有限的子集,或在使用前进行清理),因为您正在绕过 Knex 的常规保护。