如何在doctrine odm中对多个字段求和?

时间:2017-11-23 17:03:48

标签: php doctrine doctrine-odm

我想使用doctrine odm的聚合构建器来构建此查询:

db.TeamStandings.aggregate(

    // Pipeline
    [
        // Stage 1
        {
            $match: {
                "team.$id": ObjectId("5a1643fdf5d8741a883c2aeb")
            }
        },

        // Stage 2
        {
            $group: {
                "_id": { "team": "team.$id" },

                // This is the sum of multiple fields
                "games": { $sum: { $sum: ["$wins", "$losses", "$ties"] } }, 

                "wins": { $sum: "$wins" },
                "losses": { $sum: "$losses" },
                "ties": { $sum: "$ties" },
                "homeWins" : { $sum: "$homeRecord.wins" },
                "homeLosses" : { $sum: "$homeRecord.losses" },
                "homeTies" : { $sum: "$homeRecord.ties" },
                "roadWins" : { $sum: "$roadRecord.wins" },
                "roadLosses" : { $sum: "$roadRecord.losses" },
                "roadTies" : { $sum: "$roadRecord.ties" },
            }
        },

    ]
);

我在Studio3T中执行了此操作并获得以下内容:

{ 
    "_id" : {
        "team" : "team.$id"
    }, 
    "games" : NumberInt(776), 
    "wins" : NumberInt(377), 
    "losses" : NumberInt(398), 
    "ties" : NumberInt(1), 
    "homeWins" : NumberInt(218), 
    "homeLosses" : NumberInt(170), 
    "homeTies" : NumberInt(1), 
    "roadWins" : NumberInt(159), 
    "roadLosses" : NumberInt(228), 
    "roadTies" : NumberInt(0)
}

如何使用doctrine odm的聚合构建器编写这个确切的查询?

1 个答案:

答案 0 :(得分:1)

这个很棘手,因为文档不太清楚。

理论上,您创建一个嵌套的子表达式并在那里使用sum运算符:

$builder = $this->dm->createAggregationBuilder(\Documents\BlogPost::class);
$builder->group()
    ->field('id')
    ->expression(null)
    ->field('games')
    ->sum($builder->expr()->sum('$wins', '$losses', '$ties'))
;

但是,由于构建聚合构建器的方式,它不太明白在syntax阶段之外有多个表达式的总和$project,导致以下(错误)结果:< / p>

[{
    "$group": {
        "_id": null,
        "games": { "$sum": { "$sum": "$wins" } }
    }
}]

要解决此问题,请在嵌套表达式中使用$add运算符而不是$sum

$builder = $this->dm->createAggregationBuilder(\Documents\BlogPost::class);
$builder->group()
    ->field('id')
    ->expression(null)
    ->field('games')
    ->sum($builder->expr()->add('$wins', '$losses', '$ties'))
;

这将创建您希望它创建的聚合管道。

这很奇怪的原因是因为文档在$sum$group阶段使用时定义了$project的不同行为:在$group中,它接受一个参数,而在$project中它接受多个参数。但是,它在$group内的嵌套表达式中的表现并不十分清楚:您发布的聚合管道的工作原理表明它不会将子表达式视为在$group内阶段,因此允许多个参数。当我构建运算符时,我假设相反:只有在$project阶段时{@ 1}}应该接受多个参数,否则默认为一个参数语法。

我将在MongoDB ODM中为此创建一张票,我会看看是否可以轻松修复。