如何按数组内对象字段查询文档?筛选演出可用门票子文档
嘿,我来帮你搞定这两个MongoDB查询需求!先明确下你的核心诉求:一是按数组内的对象字段筛选文档,二是从演出集合里提取出有可用门票(availableTickets > 0)的记录,只返回符合条件的门票子文档,以及演出的_id和title字段。下面给你具体的实现方案:
实现方案
先预设你的Show Schema结构
为了方便示例,我先假设你的演出集合文档结构大概是这样的:
{ "_id": ObjectId("xxx"), "title": "XX演唱会", "tickets": [ { "type": "普通票", "availableTickets": 30, "price": 199 }, { "type": "VIP票", "availableTickets": 0, "price": 599 } ] }
方法1:用聚合管道(推荐,灵活性更高)
聚合管道能精准过滤数组子文档,还能按需控制返回字段,步骤很清晰:
- 先缩小范围:用
$match筛选出包含availableTickets > 0门票的演出文档,减少后续处理的数据量 - 过滤可用门票:用
$addFields结合$filter,把tickets数组里只有可用的门票留下,替换原数组 - 指定返回字段:用
$project只保留你需要的_id、title和过滤后的tickets
具体代码:
db.shows.aggregate([ // 第一步:匹配有可用门票的演出 { $match: { "tickets.availableTickets": { $gt: 0 } } }, // 第二步:过滤出真正可用的门票子文档 { $addFields: { tickets: { $filter: { input: "$tickets", as: "ticket", cond: { $gt: ["$$ticket.availableTickets", 0] } } } } }, // 第三步:只返回你需要的字段 { $project: { _id: 1, title: 1, tickets: 1 } } ])
方法2:用find()结合投影(更简洁,MongoDB 3.2+支持)
如果不想用聚合,直接在find()的投影阶段用$filter也能实现,代码更短:
db.shows.find( // 查询条件:只找有可用门票的演出 { "tickets.availableTickets": { $gt: 0 } }, // 投影:过滤门票数组,只返回指定字段 { _id: 1, title: 1, tickets: { $filter: { input: "$tickets", as: "ticket", cond: { $gt: ["$$ticket.availableTickets", 0] } } } } )
关于「按数组内的对象字段查询文档」的补充
如果你的第一个需求是单独的(比如要找特定类型且可用的门票),分两种情况处理:
- 只要数组里存在符合单个条件的子文档:直接用点语法
// 找包含VIP类型门票的演出 db.shows.find({ "tickets.type": "VIP" })
- 要找数组里同一个子文档同时满足多个条件(比如VIP票且可用):用
$elemMatch
db.shows.find({ tickets: { $elemMatch: { type: "VIP", availableTickets: { $gt: 0 } } } })
预期结果示例
假设原始文档是:
{ "_id": ObjectId("60d21b4667d0d8992e610c85"), "title": "摇滚音乐节", "tickets": [ { "type": "普通票", "availableTickets": 50 }, { "type": "VIP票", "availableTickets": 0 }, { "type": "贵宾票", "availableTickets": 20 } ] }
执行上述查询后,返回的结果会是:
{ "_id": ObjectId("60d21b4667d0d8992e610c85"), "title": "摇滚音乐节", "tickets": [ { "type": "普通票", "availableTickets": 50 }, { "type": "贵宾票", "availableTickets": 20 } ] }
内容的提问来源于stack exchange,提问作者Giovanni Cruz
相关产品推荐
相关产品推荐

