You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Knex查询Postgres jsonb列数组中的指定对象?

PostgreSQL + Knex/TypeScript:查询jsonb数组中包含指定对象的行

你的问题出在查询条件的写法上——直接用data->>? = ?是把整个description数组和单个对象做相等比较,这显然不成立,所以返回空结果。PostgreSQL针对jsonb数组的包含检查有专门的操作符和方法,下面给你两种可行的解决方案:

方案一:使用@>操作符(推荐)

@>是PostgreSQL的jsonb包含操作符,要检查数组中是否存在某个对象,只需把目标对象包装成单元素数组,然后用该操作符判断原数组是否包含这个单元素数组:

async findByDescription(description: Description) {
  // 将目标对象包装为单元素数组,适配PostgreSQL的包含检查逻辑
  const target = [description];
  const query = this.client<ItemRow>('item_details')
    .withSchema('item_schema')
    .select()
    // 用@>操作符判断数组包含关系,同时确保参数转为jsonb类型
    .whereRaw('data->\'description\' @> ?::jsonb', [JSON.stringify(target)]);

  const result = await query;
  return result;
}

逻辑说明

data->'description'取出的是jsonb数组,@>操作符要求左右两边均为jsonb类型。把target序列化为JSON字符串后转成jsonb,PostgreSQL就能准确判断原数组是否包含目标对象。

方案二:展开数组后匹配元素

如果需要更灵活的匹配逻辑(比如只匹配部分字段),可以用jsonb_array_elements把数组展开,再逐个比较元素:

async findByDescription(description: Description) {
  const query = this.client<ItemRow>('item_details')
    .withSchema('item_schema')
    .select()
    .whereRaw('EXISTS (SELECT 1 FROM jsonb_array_elements(data->\'description\') elem WHERE elem = ?::jsonb)', [JSON.stringify(description)]);

  const result = await query;
  return result;
}

关键注意事项

  • 必须把description对象序列化为JSON字符串,再转为jsonb类型,否则PostgreSQL无法正确识别为jsonb对象进行比较。
  • 绝对不能直接用=比较数组和单个对象,这种逻辑本身就不成立。

测试你提供的示例数据,两种方案都能正确返回x-y-z和a-b-c两条记录。

内容的提问来源于stack exchange,提问作者Kashyap

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 22:02:25