同一文档中3个字段的平均值

3

我在数据库中存储了一些文档,它们的“结构”完全相同。每个文档都有三个浮点值(键是“A”、“B”和“C”),我需要做的是将每个文档投影为这三个值的平均值。

我还需要除以100,所以我的计算公式是(A + B + C)/3/100。据我所知,我需要将每个文档投影为不同的输出结果,但$group在这里没有用处(因为我不是在所有文档之间平均,而是在每个文档中)。

首先,我需要将此作为MongoDB命令编写,然后将其翻译为PHP。我想我能够完成PHP部分,但我需要一些帮助来开始实际的MongoDB命令...

db.measurements.aggregate(   )

我的数据存储如下:

{ "_id" : ObjectId(xxx), "A": 22.34, "B": 23.32, "C": 75.32, "device_id": 3 }
{ "_id" : ObjectId(xxx), "A": 22.34, "B": 23.32, "C": 75.32, "device_id": 3 }
{ "_id" : ObjectId(xxx), "A": 22.34, "B": 23.32, "C": 75.32, "device_id": 3 }

当我提交一个GET请求时,我需要我的数据输出如下:
{ "_id" : ObjectId(xxx), "Average of A,B,C": 40.50, "device_id": 3 }
{ "_id" : ObjectId(xxx), "Average of A,B,C": 40.50, "device_id": 3 }
{ "_id" : ObjectId(xxx), "Average of A,B,C": 40.50, "device_id": 3 }

经过进一步的研究,似乎聚合不是我应该在这里使用的方法?如果我在php模型中插入之前计算平均值,并仅通过find()方法检索我的文档,那么是否更好呢?


请展示带有预期输出的样本文档。 - styvane
已添加到原帖。 - ugotchi
2个回答

5
您需要的是一个单一的$project管道聚合 - 它将使用可用的算术运算符为您计算平均值,并在同一管道内修改结果,以获得字段作为((A + B + C)/3)/100的计算表达式(如果您想要百分比,则需要乘以而不是除以,即计算为((A + B + C)/3)*100)。以下操作简要说明了该过程:
db.measurements.aggregate([
    {
        "$project": {               
            "device_id": 1,
            "Average of A,B,C": {
                "$divide": { // ( A + B + C )/3 )/100
                    {
                        "$divide": [ // (A + B + C )/3
                            { "$add": [ "$A", "$B", "$C" ] }, // A + B + C
                            3
                        ]
                    },
                    100
                }
            }
        }
    }
])

话虽如此,最好在应用层中进行繁重或复杂的计算任务,并让Mongo执行其数据持久性任务。


谢谢Chridam。最好在应用层中进行平均计算,并在添加到数据库之前将它们存储为附加字段。 - ugotchi
@ ggwc 不用担心。不过我不太确定你的问题中是否有错别字;你是想乘以100得到一个百分比,就像你期望的输出一样,还是说计算公式本身就是正确的,只需要除以100? - chridam
是的,它不是一个百分号。感谢您的帮助。 - ugotchi

3
从MongoDB 3.2开始,我们可以使用带有方括号[]$avg累加器运算符,在$project阶段直接高效地创建新的数组字段来完成此操作。
当然,我们还需要使用$divide算术聚合运算符将该值除以100
db.measurements.aggregate(
    [ 
        { "$project": { 
            "result": { 
                "$divide": [
                    { "$avg": [ "$a", "$b", "$c" ] }, 
                    100 
                ] 
            } 
        }} 
    ]
)

PHP中的翻译功能提供:

db.measurements.aggregate(
    array(
        array("$project" => array( 
            "result" => array( 
                "$divide" => array(
                    "$avg" => array("$a", "$b", "$c"), 
                    100 
                )
            )
        ))
    )
)

1
不过3.2的解决方案不错! - chridam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接