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

Prisma使用array_contains过滤JSON数组报JsonNullableFilter类型错误

错误产生原因
  • array_contains 是Prisma为原生数据库数组类型(比如PostgreSQL的String[]、Int[]标量数组字段)设计的过滤操作符,默认不会绑定到Json/Json?(可空JSON类型,对应报错中的JsonNullableFilter类型)字段上。
  • 触发这个报错的核心原因是:你在Schema中将存储数组的字段定义为了JSON类型,Prisma的类型校验层严格按照Schema声明的字段类型匹配可用操作符,不会因为JSON字段里实际存的是数组值就放开数组操作符的使用权限,直接调用就会抛出类型错误。
  • 新手常见踩坑点:建表时为了省事故意用JSON类型存数组,误以为值是数组就可以直接用数组类过滤语法。
正确解决方法

根据实际场景二选一即可:

方案1:改字段为原生数组类型(长期推荐,仅支持PostgreSQL等兼容原生数组的数据库)

这是性能、类型安全性最好的方案:

  1. 修改schema.prisma中的字段定义,把原来的JSON类型改成对应数据类型的原生数组,比如存字符串标签数组就写String[],存数字ID数组就写Int[]:
model Record {
  id      Int       @id @default(autoincrement())
  // 错误的原写法:tagList Json?
  tagList String[]  // 改为原生字符串数组类型
}
  1. 执行npx prisma migrate dev生成并执行数据库迁移,同步表结构。
  2. 之后就可以正常使用array_contains做过滤,不会再触发报错:
const res = await prisma.record.findMany({
  where: {
    tagList: {
      array_contains: ["Node.js"]
    }
  }
})

方案2:保留JSON字段类型,调整过滤写法(适合暂时无法改表结构的场景)

如果因为数据库不支持原生数组(比如MySQL、SQLite)或者其他原因必须保留JSON字段,不要直接在JSON字段上裸用array_contains:

  1. 如果是PostgreSQL环境,显式传入path参数指定要检查的JSON路径:根节点直接为数组时传'$'即可;如果数组是JSON结构下的某个属性(比如字段值为{ tags: ["a", "b"] }),传入对应路径如'$.tags':
// 根节点是数组的场景
const res = await prisma.record.findMany({
  where: {
    tagList: {
      path: '$', // 声明检查JSON根节点的内容
      array_contains: ["Node.js"]
    }
  }
})

// 数组是JSON内部属性的场景
const res2 = await prisma.record.findMany({
  where: {
    extraConfig: { // extraConfig是Json类型,存储结构为{ tags: ["a", "b"] }
      path: '$.tags',
      array_contains: ["Node.js"]
    }
  }
})
  1. 如果是MySQL、SQLite等不支持上述JSON数组操作语法的环境,用原生查询兜底实现:
// MySQL 环境示例
const targetTag = "Node.js"
const res = await prisma.$queryRaw`
  SELECT * FROM Record
  WHERE JSON_CONTAINS(tagList, JSON_ARRAY(${targetTag}))
`

注意:JSON字段存数组的写法无法利用原生数组的索引优化,大数据量下查询性能会明显差于原生数组字段,有条件优先选择方案1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 14:51:20