use*_*ser 0 mongodb aggregation-framework
我收集了产品,这些产品都有评估.我需要选择具有最高评估平均值的产品.问题是我可以按平均分组产品但我无法按平均分组并选择平均值最高的产品.
要重现我的问题,请按照下列步骤操作:
插入产品:
db.products.insert([
{
name: "Product1",
price: 1000,
features: {
feature1: 0.8,
feature2: 23
},
tags: ["tag1", "tag2", "tag3", "tag4"],
assessments: [
{name: "John", assessment: 3},
{name: "Anna", assessment: 4},
{name: "Kyle", assessment: 3.6}
]
},
{
name: "Product2",
price: 1200,
features: {
feature1: 4,
feature2: 4000,
feature3: "SDS"
},
tags: ["tag1"],
assessments: [
{name: "John", assessment: 5},
{name: "Richard", assessment: 4.8}
]
},
{
name: "Product3",
price: 450,
features: {
feature1: 1.3,
feature2: 60
},
tags: ["tag1", "tag2"],
assessments: [
{name: "Anna", assessment: 5},
{name: "Robert", assessment: 4},
{name: "John", assessment: 4},
{name: "Julia", assessment: 3}
]
},
{
name: "Product4",
price: 900,
features: {
feature1: 1700,
feature2: 17
},
tags: ["tag1", "tag2", "tag3"],
assessments: [
{name: "Monica", assessment: 3},
{name: "Carl", assessment: 4}
]
}
])
Run Code Online (Sandbox Code Playgroud)
我希望通过平均评估进行分组,并选择最高平均值的产品.
我这样做:
db.products.aggregate([
{ $unwind : "$assessments" },
{ $group:
{
_id: "$name",
avg_assessment: {$avg: "$assessments.assessment"}
}
},
{ $project:
{
_id: 0,
product: "$_id",
avg_assessment: 1
}
}
])
Run Code Online (Sandbox Code Playgroud)
此查询的结果是:
{ "avg_assessment" : 3.5, "product" : "Product4" }
{ "avg_assessment" : 4, "product" : "Product3" }
{ "avg_assessment" : 4.9, "product" : "Product2" }
{ "avg_assessment" : 3.533333333333333, "product" : "Product1" }
Run Code Online (Sandbox Code Playgroud)
尼斯.然后我尝试使用以下查询选择具有最高平均值的产品:
db.products.aggregate([
{ $unwind : "$assessments" },
{ $group:
{
_id: "$name",
avg_assessment: { $max: {$avg: "$assessments.assessment"}}
}
},
{ $project:
{
_id: 0,
product: "$_id",
avg_assessment: 1
}
}
])
Run Code Online (Sandbox Code Playgroud)
但结果是相同的,但有四舍五入的值:
{ "avg_assessment" : 4, "product" : "Product4" }
{ "avg_assessment" : 5, "product" : "Product3" }
{ "avg_assessment" : 5, "product" : "Product2" }
{ "avg_assessment" : 4, "product" : "Product1" }
Run Code Online (Sandbox Code Playgroud)
这是怎么回事?哪里有问题?
您可以尝试以下聚合.没有$unwind此需要.
计算$avg每个评估,然后进行排序.
$group与$first挑选具有最高平均价值的评估.
添加$project阶段以限制字段.
db.products.aggregate([
{ "$addFields" : {"avg_assessment":{"$avg":"$assessments.assessment" }}},
{ "$sort":{"avg_assessment":-1}},
{ "$group":
{
"_id": null,
"highest_avg_assessment": { $first:"$$ROOT"}
}
}
])
Run Code Online (Sandbox Code Playgroud)