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

如何在Doctrine ODM中使用文档自身其他字段值更新指定字段

问题原因

普通的Doctrine ODM set() 方法仅支持写入固定字面量,不会将你传入的$rate.total这类字符串识别为文档字段引用,因此无法实现同文档字段间的运算更新。

解决方案

MongoDB 4.2及以上版本支持使用聚合管道执行更新操作,可以直接引用文档现有字段做运算,Doctrine ODM 2.0及以上版本已内置对该特性的支持,你可以通过pipe()方法实现需求,修正后的代码如下:

public function updateCountAndRate(string $service, string $expert, float $rate, bool $comment = false)
{
    $rateKey = (int)round($rate);
    $queryBuilder = $this->createQueryBuilder();

    // 普通增量更新逻辑不变
    $queryBuilder->field(sprintf('rate.counts.%d', $rateKey))->inc(1);
    $queryBuilder->field('rate.total')->inc(1);
    if ($comment) {
        $queryBuilder->field('comments')->inc(1);
    }

    // 聚合管道实现字段间运算更新平均值
    $queryBuilder->pipe([
        '$set' => [
            'rate.average' => [
                '$divide' => [
                    [
                        '$add' => [
                            ['$multiply' => ['$rate.average', '$rate.total']],
                            $rate
                        ]
                    ],
                    ['$add' => ['$rate.total', 1]]
                ]
            ]
        ]
    ]);

    $queryBuilder->updateOne()
        ->getQuery()
        ->execute();
}

注意事项

  • 该方案要求MongoDB服务端版本 >= 4.2,Doctrine ODM版本 >= 2.0
  • 整个更新操作是原子性的,不存在并发更新导致的数据不一致问题
  • 如果你使用的是不支持管道更新的旧版本,只能先查询出对应文档,在PHP端计算出新的平均值后再执行更新,这种情况建议配合乐观锁避免并发覆盖问题

内容的提问来源于stack exchange,提问作者Hamid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 21:24:01