我有一个文档,其中包含一个名为“等级”的字段。这是一个对象数组,每个对象都包含userId和ratingValue
ratings: Array
0: Object
userId: "uidsample1"
ratingValue: 5
1: Object
userId:"uidsample2"
ratingValue:1.5
当阵列中的一个评级被更新或添加时,我想做一个聚合管道来计算新的平均值。然后,我想将该值作为一个称为averageRating的新字段放入文档中。
我尝试平仓,然后$ avg的$ add字段:“ ratings.ratingValue”,但是它添加到平仓的文档中,但没有得到平均值。看起来像这样(自从在指南针上测试之后就不完全如此)
db.test.aggregate{
[
{
$unwind: {
path: "$ratings"
}
},
{
$addFields {
averageRating: {
$avg: "$ratings.ratingValue"
}
}
}
]
}
对此有什么好的查询结构?
答案 0 :(得分:1)
在py4j.protocol.Py4JError: An error occurred while calling z:org.apache.spark.sql.functions.abs. Trace:
**py4j.Py4JException: Method abs([class java.lang.Integer]) does not exist
at**
py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:318)
at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:339)
at py4j.Gateway.invoke(Gateway.java:276)
at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
at py4j.commands.CallCommand.execute(CallCommand.java:79)
at py4j.GatewayConnection.run(GatewayConnection.java:238)
at java.lang.Thread.run(Thread.java:745)
之后使用$group
,如下所述计算 averageRating 。聚合是读取操作。您需要稍后再更新文档。
$unwind
答案 1 :(得分:1)
您实际上不需要$unwind
和$group
来计算平均值,这些操作成本很高
您可以简单地将$addFields
与$avg
db.col.aggregate([
{$addFields : {averageRating : {$avg : "$ratings.ratingValue"}}}
])
样本收集和汇总
> db.t62.drop()
true
> db.t62.insert({data : {ratings : [{val : 1}, {val : 2}]}})
WriteResult({ "nInserted" : 1 })
> db.t62.find()
{ "_id" : ObjectId("5c44d9719d56bf65be5ab2e6"), "data" : { "ratings" : [ { "val" : 1 }, { "val" : 2 } ] } }
> db.t62.aggregate([{$addFields : {avg : {$avg : "$data.ratings.val"}}}])
{ "_id" : ObjectId("5c44d9719d56bf65be5ab2e6"), "data" : { "ratings" : [ { "val" : 1 }, { "val" : 2 } ] }, "avg" : 1.5 }