MongoDB:确定是否有任何对象具有特定子数组值的特定计数
MongoDB: determining if there are any objects with a specific count for a particular sub-array value
基本上,我有:
- 一个
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" ]
},
]
}
我需要确定是否有任何乐队包含多个成员SINGER角色。
一些简单的选项:
db.collection.aggregate([
{
$unwind: "$players"
},
{
$unwind: "$players.roles"
},
{
$match: {
"players.roles": "SINGER"
}
},
{
$group: {
_id: "$_id",
cnt: {
$sum: 1
}
}
},
{
$match: {
cnt: {
$gt: 1
}
}
}
])
解释:
- 展开第一个数组
- 展开第二个数组
- 仅过滤角色 SINGER
- 按乐队 _id 分组并计算 SINGER 角色。
- 只过滤超过 1 个 SINGER
的乐队
$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 stage。
这个查询似乎给了我我需要的东西:
db.bands.aggregate([
{
$addFields: {
players: {
$ifNull: [
"$players",
[]
]
}
}
},
{
"$match": {
"$expr": {
"$gt": [
{
"$size": {
"$filter": {
"input": "$players",
"as": "player",
"cond": {
"$in": [
"SINGER",
"$$player.roles"
]
}
}
}
},
1
]
}
}
}
])
基本上,我有:
- 一个
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" ]
},
]
}
我需要确定是否有任何乐队包含多个成员SINGER角色。
一些简单的选项:
db.collection.aggregate([
{
$unwind: "$players"
},
{
$unwind: "$players.roles"
},
{
$match: {
"players.roles": "SINGER"
}
},
{
$group: {
_id: "$_id",
cnt: {
$sum: 1
}
}
},
{
$match: {
cnt: {
$gt: 1
}
}
}
])
解释:
- 展开第一个数组
- 展开第二个数组
- 仅过滤角色 SINGER
- 按乐队 _id 分组并计算 SINGER 角色。
- 只过滤超过 1 个 SINGER 的乐队
$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 stage。
这个查询似乎给了我我需要的东西:
db.bands.aggregate([
{
$addFields: {
players: {
$ifNull: [
"$players",
[]
]
}
}
},
{
"$match": {
"$expr": {
"$gt": [
{
"$size": {
"$filter": {
"input": "$players",
"as": "player",
"cond": {
"$in": [
"SINGER",
"$$player.roles"
]
}
}
}
},
1
]
}
}
}
])