
本文介绍如何使用 prisma 的关系过滤语法(`some`)精准查询拥有至少一个菜单项的子分类,避免因误用 `not: null` 导致的语法错误,并确保返回结果同时包含关联的菜单数据。
在 Prisma 中,对一对多关系(如 SubCategory 与 Menu)进行“非空”条件筛选时,不能直接对数组字段使用 where: { id: { not: null } }——这不仅逻辑错误(menu 字段本身是数组,不可能为 null),更会触发 Prisma 客户端报错:"Argument 'not' must not be null."。根本原因在于:menu 是一个关系字段(类型为 Menu[]),其值始终是数组(空数组 [] 或非空数组),而非可为 null 的标量或对象。
✅ 正确做法是使用 Prisma 提供的关系过滤操作符 some,它专用于判断「至少存在一个满足条件的关联记录」。当传入空对象 {} 时,some: {} 表示「存在任意一条关联的 Menu 记录」,即等价于「菜单非空」。
以下是推荐的完整查询代码:
const topCategories = await this.prisma.subCategory.findMany({
where: {
menu: {
some: {}, // ✅ 关键:筛选拥有至少一个 Menu 的 SubCategory
},
},
include: {
menu: true, // ✅ 同时加载所有匹配的菜单数据
},
orderBy: {
id: 'desc',
},
take: 50,
});⚠️ 注意事项:
- some: {} 不等同于 some: { id: { not: 0 } } 等复杂条件——空对象即表示“存在任意匹配项”,语义清晰且性能友好;
- 若需进一步筛选菜单(例如只包含已启用的菜单),可扩展为 some: { isActive: true };
- 不要混淆 include 中的 where(用于过滤被包含的关联数据)与 findMany 根级 where(用于筛选主模型本身)。前者影响返回的 menu 子集,后者决定哪些 subCategory 被选中;
- menu 关系在模型中未定义 @relation(fields: [...]) 外键字段,说明你可能采用隐式多对多或通过中间表管理。请确保数据库中 Menu 表实际存在指向 SubCategory 的外键(如 subCategoryId),否则 some 过滤将无法生效。
总结:当目标是「查找拥有至少一个关联记录的父级模型」时,始终优先使用 relationField: { some: {} };这是 Prisma 关系查询的核心范式,兼具准确性、可读性与执行效率。










