Reputation: 792
Essentially, I have:
bands
collectionplayers
roles
(string)E.g.:
// a band
{
_id: 1,
players: [
{
name: "George",
roles: [ "GUITAR" ]
},
{
name: "John",
roles: [ "SINGER", "GUITAR" ]
},
{
name: "Paul",
roles: [ "SINGER", "BASS GUITAR" ]
},
{
name: "Ringo",
roles: [ "DRUMS" ]
},
]
}
I need to determine if there is any band which contains more than one member having the SINGER role.
Upvotes: 0
Views: 54
Reputation: 792
This query seems to give me what I need:
db.bands.aggregate([
{
$addFields: {
players: {
$ifNull: [
"$players",
[]
]
}
}
},
{
"$match": {
"$expr": {
"$gt": [
{
"$size": {
"$filter": {
"input": "$players",
"as": "player",
"cond": {
"$in": [
"SINGER",
"$$player.roles"
]
}
}
}
},
1
]
}
}
}
])
Upvotes: 1
Reputation: 37108
An alternative to the $unwind / $group
solution would be $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
}
}
])
It should be a bit faster as it doesn't have blocking $group stage.
Upvotes: 2
Reputation: 10737
Some easy option:
db.collection.aggregate([
{
$unwind: "$players"
},
{
$unwind: "$players.roles"
},
{
$match: {
"players.roles": "SINGER"
}
},
{
$group: {
_id: "$_id",
cnt: {
$sum: 1
}
}
},
{
$match: {
cnt: {
$gt: 1
}
}
}
])
explained:
Upvotes: 1