如何用Prisma Client查询MongoDB子数组并筛选热门商品
如何用Prisma查询MongoDB分类集合时仅保留热门商品
问题背景
我用Prisma作为ORM操作MongoDB,现有如下Schema:
model Category { id String @id @default(auto()) @map("_id") @db.ObjectId name String // 补充:原Schema遗漏该字段,匹配实际数据结构 products Product[] } type Product { name String popular Boolean }
MongoDB分类集合的示例数据:
const category = [ { name: "Juice", products: [ { name: "Mojito", popular: true }, { name: "Lemon mint", popular: false }, ], }, { name: "Coffee", products: [ { name: "Caramel", popular: true }, { name: " mint", popular: false }, ], } ];
我需要查询分类集合,仅保留每个分类下popular为true的商品,期望结果:
[ { name: "Juice", products: [{ name: "Mojito", popular: true }], }, { name: "Coffee", products: [{ name: "Caramel", popular: true }], }, ];
我尝试用where子句的some操作符查询:
const categoriesWithPopularProduct = db.category.findMany({ where: { products: { some: { popular: { equals: true }, }, }, }, });
但这个查询返回的是分类下的所有商品,而非仅热门商品,请问该如何实现需求?
解决方案
你之前的where.some仅用于筛选符合条件的分类(即包含至少一个热门商品的分类),但不会修改分类下的products数组内容。要实现过滤数组内的元素,需要结合Prisma的select和MongoDB的聚合表达式$filter:
方法1:使用findMany配合select中的$filter
const categoriesWithPopularProduct = await db.category.findMany({ select: { name: true, products: { $filter: { input: "$products", cond: { $eq: ["$$this.popular", true] } } } }, where: { // 保留存在热门商品的分类,避免返回products为空的分类 products: { some: { popular: true } } } });
方法2:使用aggregateRaw执行MongoDB原生聚合管道
如果需要更复杂的操作,也可以直接用原生聚合管道:
const categoriesWithPopularProduct = await db.category.aggregateRaw({ pipeline: [ // 过滤每个分类的products数组,仅保留热门商品 { $addFields: { products: { $filter: { input: "$products", cond: { $eq: ["$$this.popular", true] } } } } }, // 过滤掉products为空的分类 { $match: { products: { $ne: [] } } } ] });
原理说明
$filter是MongoDB的聚合操作符,用于遍历数组并根据条件筛选元素,$$this代表数组中的当前元素。- 搭配
where.some(或聚合管道中的$match)可以确保最终结果只包含有热门商品的分类,不会出现products为空数组的条目。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

