本质上,我有:
bands
集合- 每个频带可以具有也可以不具有
players
的阵列 - 每个玩家都有一个
roles
(字符串(数组
例如:
// a band
{
_id: 1,
players: [
{
name: "George",
roles: [ "GUITAR" ]
},
{
name: "John",
roles: [ "SINGER", "GUITAR" ]
},
{
name: "Paul",
roles: [ "SINGER", "BASS GUITAR" ]
},
{
name: "Ringo",
roles: [ "DRUMS" ]
},
]
}
我需要确定是否有任何乐队包含多名成员担任歌手角色。
$unwind / $group
解决方案的替代方案是$filter:
db.collection.aggregate([
{
$match: {
"players.roles": "GUITAR"
}
},
{
"$set": {
"member_cnt": {
$size: {
$filter: {
input: "$players",
cond: {
$in: [
"GUITAR",
"$$this.roles"
]
}
}
}
}
}
},
{
$match: {
"member_cnt": {
$gt: 1
}
}
},
{
"$project": {
member_cnt: 0
}
}
])
它应该更快一点,因为它没有阻塞$group阶段。
一些简单的选项:
db.collection.aggregate([
{
$unwind: "$players"
},
{
$unwind: "$players.roles"
},
{
$match: {
"players.roles": "SINGER"
}
},
{
$group: {
_id: "$_id",
cnt: {
$sum: 1
}
}
},
{
$match: {
cnt: {
$gt: 1
}
}
}
])
解释:
- 展开第一个数组
- 展开第二个阵列
- 仅筛选SINGER角色
- 按band_id分组并计数SINGER角色
- 使用>1名歌手
操场
这个查询似乎给了我所需要的:
db.bands.aggregate([
{
$addFields: {
players: {
$ifNull: [
"$players",
[]
]
}
}
},
{
"$match": {
"$expr": {
"$gt": [
{
"$size": {
"$filter": {
"input": "$players",
"as": "player",
"cond": {
"$in": [
"SINGER",
"$$player.roles"
]
}
}
}
},
1
]
}
}
}
])