mongodb中多个文档数组中相等元素的计数

8dtrkrch  于 2023-02-07  发布在  Go
关注(0)|答案(3)|浏览(149)

我正在做一个简单的程序,通过n个玩家来计算特殊单位的总数。
我有类似的文档(简化),其中数组rosterUnits的长度可以是0到7。总共有7个特殊单位。我需要知道每个单位的球员有多少在名册上。

{
  {
    _id: ObjectId(...),
    member: {
      rosterUnits: [ "Unit1", "Unit2", "Unit3", "Unit4"]
    }
  },
  {
    _id: ObjectId(...),
    member: {
      rosterUnits: [ "Unit1", "Unit3"]
    }
  },
  ...
}

预期结果如下所示:

{
  _id: ...
  result: [
    {
      name: "Unit1"
      count: 2
    },
    {
      name: "Unit2"
      count: 1
    },
    {
      name: "Unit3"
      count: 2
    },
    ...
    {
      name: "Unit7"
      count: 0
    }
  ]
}

如何使用聚合管道实现这一点?

编辑(2023年2月7日)

对不起,各位,我以为我在这里提供了足够的细节,但是...文件非常大,直到这个阶段的管道是非常长的。我想节省你的麻烦与文件
我有一个公会,最多有50名玩家。我搜索公会,然后$解开公会成员,$查找成员以获得成员。
这是我提出的完整查询:

db.getCollection('guilds').aggregate([
    { $match: { 'profile.id': 'jrl9Q-_CRDGdMyNjTQH1rQ' } },
    //{ $match: { 'profile.id': { $in : ['jrl9Q-_CRDGdMyNjTQH1rQ', 'Tv_j9nhRTgufvH7C7oUYAA']} } },
    { $project: { member: 1, profile: 1 } },
    { $unwind: "$member" },
    {
        $lookup: {
            from: "players",
            localField: "member.playerId",
            foreignField: "playerId",
            pipeline: [
                {
                    $project: {
                        profileStat: 1,
                        rosterUnit: {
                            $let: {
                                vars: { gls: ["JABBATHEHUTT:SEVEN_STAR", "JEDIMASTERKENOBI:SEVEN_STAR", "GRANDMASTERLUKE:SEVEN_STAR", "LORDVADER:SEVEN_STAR", "GLREY:SEVEN_STAR", "SITHPALPATINE:SEVEN_STAR", "SUPREMELEADERKYLOREN:SEVEN_STAR"], },
                                in: {
                                    $reduce: {
                                        input: "$rosterUnit",
                                        initialValue: [],
                                        in: {
                                            $cond: {
                                                if: { $gt: [{ $indexOfArray: ["$$gls", "$$this.definitionId"] }, -1] },
                                                then: { $concatArrays: ["$$value", [{ definitionId: "$$this.definitionId", count: 1 }]] },
                                                else: { $concatArrays: ["$$value", []] }
                                            }
                                        },
                                    }
                                }
                            }
                        }
                    }
                }
            ],
            as: "member"
        }
    },
    {
        $addFields: {
            member: { $arrayElemAt: ["$member", 0] },
            gpStats: {
                $let: {
                    vars: { member: { $arrayElemAt: ["$member", 0] } },
                    in: {
                        $reduce: {
                            input: "$$member.profileStat",
                            initialValue: {},
                            in: {
                                characterGp: {
                                    $arrayElemAt: [
                                        "$$member.profileStat.value",
                                        {
                                            $indexOfArray: [
                                                "$$member.profileStat.nameKey",
                                                "STAT_CHARACTER_GALACTIC_POWER_ACQUIRED_NAME"
                                            ]
                                        }
                                    ]
                                },
                                shipGp: {
                                    $arrayElemAt: [
                                        "$$member.profileStat.value",
                                        {
                                            $indexOfArray: [
                                                "$$member.profileStat.nameKey",
                                                "STAT_SHIP_GALACTIC_POWER_ACQUIRED_NAME"
                                            ]
                                        }
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    {
        $group: {
            _id: "$profile.id",
            guildName: { $first: "$profile.name" },
            memberCount: { $first: "$profile.memberCount" },
            guildGp: { $first: "$profile.guildGalacticPower" },
            totalGp: { $sum: { $sum: [{ $toInt: "$gpStats.characterGp" }, { $toInt: "$gpStats.shipGp" }] } },
            avgTotalGp: { $avg: { $sum: [{ $toInt: "$gpStats.characterGp" }, { $toInt: "$gpStats.shipGp" }] } },
            characterGp: { $sum: { $toInt: "$gpStats.characterGp" } },
            shipGp: { $sum: { $toInt: "$gpStats.shipGp" } },

        }
    }

])

我想添加新的字段到组中,得到上面想要的结果。如果我在member.rosterUnit上做了$unwind,我该如何返回到成员分组?
(再次打扰,这是我的第一个问题)

s8vozzvw

s8vozzvw1#

  • 使用$unwindrosterUnits数组分解为单独的文档。
  • 然后使用$grouprosterUnits值对文档进行分组,并计算每个单元的计数。
  • 然后使用$project化输出,使其仅包含name和count字段。
db.collection.aggregate([
    { 
        $unwind: "$member.rosterUnits" 
    },
    { 
        $group: { 
            _id: "$member.rosterUnits", 
            count: { $sum: 1 } 
        } 
    },
    { 
        $project: { 
            _id: 0, 
            name: "$_id", 
            count: "$count" 
        } 
    }
])
bpzcxfmw

bpzcxfmw2#

是的,我认为最好的方法是使用聚合。
我相信有更好的方法来解决这个问题,但这里有一个解决方案,我希望它对你的朋友有效。
基本上,我们将使用“$group”聚合,并在其中使用运算符“$cond”和“$in”,我们将逐个验证是否找到了搜索的元素。如果找到了,我们将添加1,如果没有找到,则添加0。

  • 我建议你下载mongodb指南针试试 *
    合计:
[{
     $group: {
      _id: null,
      Unit1: {
       $sum: {
        $cond: [
         {
          $in: [
           'Unit1',
           '$member.rosterUnits'
          ]
         },
         1,
         0
        ]
       }
      },
      Unit2: {
       $sum: {
        $cond: [
         {
          $in: [
           'Unit2',
           '$member.rosterUnits'
          ]
         },
         1,
         0
        ]
       }
      },
      Unit3: {
       $sum: {
        $cond: [
         {
          $in: [
           'Unit3',
           '$member.rosterUnits'
          ]
         },
         1,
         0
        ]
       }
      },
      Unit4: {
       $sum: {
        $cond: [
         {
          $in: [
           'Unit4',
           '$member.rosterUnits'
          ]
         },
         1,
         0
        ]
       }
      },
      Unit5: {
       $sum: {
        $cond: [
         {
          $in: [
           'Unit5',
           '$member.rosterUnits'
          ]
         },
         1,
         0
        ]
       }
      },
      Unit6: {
       $sum: {
        $cond: [
         {
          $in: [
           'Unit6',
           '$member.rosterUnits'
          ]
         },
         1,
         0
        ]
       }
      },
      Unit7: {
       $sum: {
        $cond: [
         {
          $in: [
           'Unit7',
           '$member.rosterUnits'
          ]
         },
         1,
         0
        ]
       }
      }
     }
    }, {
     $project: {
      _id: 0
     }
    }]
wgmfuz8q

wgmfuz8q3#

质询

  • 因为您要计算可能不存在的值,所以可以手动进行分组,并执行条件计数
  • 在分组之后你可以做额外的转换(如果你真的需要期望的输出完全一样)。对象到数组,Map给予字段名(名称,计数)

Playmongo

aggregate(
[{"$unwind": "$member.rosterUnits"},
 {"$group": 
   {"_id": null,
    "Unit1": 
     {"$sum": 
       {"$cond": [{"$eq": ["$member.rosterUnits", "Unit1"]}, 1, 0]}},
    "Unit2": 
     {"$sum": 
       {"$cond": [{"$eq": ["$member.rosterUnits", "Unit2"]}, 1, 0]}},
    "Unit3": 
     {"$sum": 
       {"$cond": [{"$eq": ["$member.rosterUnits", "Unit3"]}, 1, 0]}},
    "Unit4": 
     {"$sum": 
       {"$cond": [{"$eq": ["$member.rosterUnits", "Unit4"]}, 1, 0]}},
    "Unit5": 
     {"$sum": 
       {"$cond": [{"$eq": ["$member.rosterUnits", "Unit5"]}, 1, 0]}},
    "Unit6": 
     {"$sum": 
       {"$cond": [{"$eq": ["$member.rosterUnits", "Unit6"]}, 1, 0]}},
    "Unit7": 
     {"$sum": 
       {"$cond": [{"$eq": ["$member.rosterUnits", "Unit7"]}, 1, 0]}}}},
 {"$unset": ["_id"]},
 {"$project": 
   {"result": 
     {"$map": 
       {"input": {"$objectToArray": "$$ROOT"},
        "in": {"name": "$$this.k", "count": "$$this.v"}}}}}])

相关问题