You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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);

解决方案

代码问题分析

  1. 查询条件错误:["Blocks"=>"FirstBlock"]是判断Blocks字段等于字符串FirstBlock,而非检查该子对象存在
  2. 字段访问错误:$row["candidate_id"]直接访问根节点,但candidate_id嵌套在Blocks的子对象中
  3. 覆盖不全:仅处理了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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 06:30:57