如何在PHP中访问MongoDB嵌套对象的candidate_id并统计票数
问题:获取MongoDB嵌套对象中的candidate_id并统计得票数
需求
从MongoDB的嵌套对象中提取candidate_id,统计每位候选人的得票数,最终票数以整数形式展示。
MongoDB数据结构
{ "_id": { "$oid": "637a7e16e490c4baadd9437f" }, "civilid": "12769219", "Blocks": { "BaseBlock": { "nonce": {"$numberInt": "0"}, "index": {"$numberInt": "0"}, "timestamp": "11-20-2022 22:39:30.082200", "candidate_id": "0", "previousHash": "0", "hash": "d19f8d1d4bba2c22a82c1f3691f364fac86e992075bbd6a6ad239188d7a242e7" }, "FirstBlock": { "nonce": {"$numberInt": "107675"}, "index": {"$numberInt": "1"}, "timestamp": "11-20-2022 22:39:30.082300", "candidate_id": "103", "previousHash": "d19f8d1d4bba2c22a82c1f3691f364fac86e992075bbd6a6ad239188d7a242e7", "hash": "0000ac30bf8b97a9525d64a10a990ccf2b1fe4ee0c7c91fe665e572f0a39e11f" }, "SeconedBlock": { "nonce": {"$numberInt": "124478"}, "index": {"$numberInt": "2"}, "timestamp": "11-20-2022 22:39:30.082300", "candidate_id": "103", "previousHash": "0000ac30bf8b97a9525d64a10a990ccf2b1fe4ee0c7c91fe665e572f0a39e11f", "hash": "0000a709f4faf36466cbd37ec34e09b64db309e306d238b586d4a6ae669f28da" } } }
尝试的代码(PHP)
$con = new MongoDB\Client('mongodb+srv://<username>:<password>@<cluster>.ivtq9gb.mongodb.net/?retryWrites=true&w=majority'); $db = $con->VoterDatabase; $collection3 = $db->Votes; $cursor3 = $collection3->find(["Blocks"=>"FirstBlock"]); $result = $cursor3->toArray(); foreach ($result as $row) { $block[] = $row["candidate_id"]; } var_dump($cursor3);
解决方案
代码问题分析
- 查询条件错误:
["Blocks"=>"FirstBlock"]是判断Blocks字段等于字符串FirstBlock,而非检查该子对象存在 - 字段访问错误:
$row["candidate_id"]直接访问根节点,但candidate_id嵌套在Blocks的子对象中 - 覆盖不全:仅处理了
FirstBlock,遗漏了BaseBlock、SeconedBlock等其他块
方式一:PHP端遍历处理
先拉取所有文档,再遍历每个文档内的所有块,提取ID并统计票数:
$con = new MongoDB\Client('mongodb+srv://<username>:<password>@<cluster>.ivtq9gb.mongodb.net/?retryWrites=true&w=majority'); $db = $con->VoterDatabase; $collection3 = $db->Votes; // 获取所有投票文档 $cursor = $collection3->find(); $documents = $cursor->toArray(); $voteCounts = []; foreach ($documents as $doc) { // 遍历当前文档下的所有块 foreach ($doc['Blocks'] as $blockData) { // 将字符串ID转为整数 $candidateId = (int)$blockData['candidate_id']; // 更新票数统计 $voteCounts[$candidateId] = isset($voteCounts[$candidateId]) ? $voteCounts[$candidateId] + 1 : 1; } } // 输出统计结果 print_r($voteCounts);
方式二:MongoDB聚合查询(推荐)
利用MongoDB聚合管道直接在数据库端完成提取和统计,效率更高:
$con = new MongoDB\Client('mongodb+srv://<username>:<password>@<cluster>.ivtq9gb.mongodb.net/?retryWrites=true&w=majority'); $db = $con->VoterDatabase; $collection3 = $db->Votes; $pipeline = [ // 将Blocks对象转为键值对数组,方便处理所有子块 ['$project' => [ 'blocks' => ['$objectToArray' => '$Blocks'] ]], // 展开数组,每个块单独成为一个文档 ['$unwind' => '$blocks'], // 提取candidate_id并转为整数 ['$project' => [ 'candidate_id' => ['$toInt' => '$blocks.v.candidate_id'] ]], // 按候选人ID分组统计票数 ['$group' => [ '_id' => '$candidate_id', 'vote_count' => ['$sum' => 1] ]], // 可选:按票数从高到低排序 ['$sort' => ['vote_count' => -1]] ]; $cursor = $collection3->aggregate($pipeline); $voteStats = $cursor->toArray(); // 输出结果 print_r($voteStats);
关键说明
$objectToArray:把Blocks这个嵌套对象转为{k: 块名称, v: 块数据}的数组,统一处理所有块$unwind:将数组拆分为单个文档,方便后续分组统计$toInt:将字符串类型的candidate_id转换为整数类型$group:按候选人ID分组,用$sum累加票数
内容的提问来源于stack exchange,提问作者The--King 464
相关产品推荐
相关产品推荐

