我是MongoDB的新手并且学习编写mongodb查询。我需要以下问题的帮助:
输入数据是一个集合student
,有五个记录:
[
{
"_id":0,
"name":"Maxy",
"results":[
{
"subject":"maths",
"score":1.46
},
{
"subject":"english",
"score":11.78
},
{
"subject":"history",
"score":6.67
}
]
},
{
"_id":1,
"name":"Nancy",
"results":[
{
"subject":"maths",
"score":60.06
},
{
"subject":"english",
"score":52.79
},
{
"subject":"history",
"score":71.76
}
]
},
{
"_id":2,
"name":"Peter",
"results":[
{
"subject":"maths",
"score":27.03
},
{
"subject":"english",
"score":6.30
},
{
"subject":"history",
"score":20.18
}
]
},
{
"_id":3,
"name":"Harry",
"results":[
{
"subject":"maths",
"score":71.64
},
{
"subject":"english",
"score":24.80
},
{
"subject":"history",
"score":1.69
}
]
},
{
"_id":4,
"name":"Paxy",
"results":[
{
"subject":"maths",
"score":28.68
},
{
"subject":"english",
"score":90.29
},
{
"subject":"history",
"score":34.41
}
]
}
]
我需要得到数学失败的学生数量"主题,通过分数为35.
我尝试了以下方法:
// Will give count of students who failed in subject:maths
var count = db.student.find({
results : {
$elemMatch: {
subject: "maths",
score: { $lt: 35 }
}
}
}).count() // ==>> 3
// Total students
var total = db.student.count() // ==>> 5
// Percentage
var percentage = count*100/total // ==>> 3*100/5=60%
是否可以计算学生的数量和百分比在数学"主题在一个查询中?
答案 0 :(得分:3)
这是在集合上使用聚合执行的另一个选项:
db.student.aggregate([
{$unwind:"$results"},
{$match: {"results.subject": "maths"}},
{$group: {
_id: null,
totalCount: {$sum:1},
failCount: {$sum: { "$cond": [{ "$lt": ["$results.score", 35 ] }, 1, 0 ] }}}},
{$project: {
_id : 0,
totalCount : 1,
failCount : 1,
failPercent: {
$multiply: [ { $divide: ["$failCount", "$totalCount"] }, 100 ]
}
}}
])
仅当结果包含数学结果时,学生记录才被视为总计;一名学生希望得到一个数学结果。
管道运营商:
放松 - >获得每个主题的单独行
匹配 - >仅考虑数学结果
组 - >运行分组以获得总计数;使用条件来识别失败的计数
项目 - >项目所需的元素和结果输出百分比
{
"totalCount" : 5,
"failCount" : 3,
"failPercent" : 60
}
答案 1 :(得分:0)
您需要使用MongoDB的聚合框架为单个查询运行聚合操作。考虑运行以下管道以获得所需的结果:
db.student.aggregate([
{
"$project": {
"maths_result": {
"$arrayElemAt": [
{
"$filter": {
"input": "$results",
"as": "res",
"cond": {
"$eq": ["$$res.subject", "maths"]
}
}
},
0
]
}
}
},
{
"$project": {
"maths_fail": { "$lt": ["$maths_result.score", 35 ] }
}
},
{
"$group": {
"_id": null,
"total": { "$sum": 1 },
"fail_count": { "$sum": { "$cond": ["$maths_fail", 1, 0 ] } }
}
},
{
"$project": {
"percentage_maths_fail": {
"$multiply": [
{ "$divide": ["$fail_count", "$total"] },
100
]
}
}
}
])
执行管道时,MongoDB将运营商互相管道。 "管"这里采用Linux的含义:运算符的输出成为以下运算符的输入。每个运算符的结果是一个新的文档集合。所以Mongo按如下方式执行上述管道:
collection | $project | $project | $group | $project => result
第一个管道步骤 $project
,与SQL中的SELECT
语句非常相似,在这种情况下,它用于创建一个具有单个元素的新字段results
数组。这可以通过 $arrayElemAt
和$ filter运算符实现。 $filter
运算符表达式将返回一个与主题字段为" maths"并且 $arrayElemAt
返回数组中的第一个元素,类似于展平它。
因此,仅使用此步骤运行管道将产生结果:
db.student.aggregate([
{
"$project": {
"maths_result": {
"$arrayElemAt": [
{
"$filter": {
"input": "$results",
"as": "res",
"cond": {
"$eq": ["$$res.subject", "maths"]
}
}
},
0
]
}
}
}
])
示例输出
/* 1 */
{
"_id" : 0,
"maths_result" : {
"subject" : "maths",
"score" : 1.46
}
}
/* 2 */
{
"_id" : 1,
"maths_result" : {
"subject" : "maths",
"score" : 60.06
}
}
/* 3 */
{
"_id" : 2,
"maths_result" : {
"subject" : "maths",
"score" : 27.03
}
}
/* 4 */
{
"_id" : 3,
"maths_result" : {
"subject" : "maths",
"score" : 71.64
}
}
/* 5 */
{
"_id" : 4,
"maths_result" : {
"subject" : "maths",
"score" : 28.68
}
}
下一个 $project
运算符的第二步将重构上述字段,以便为失败条件返回true或false:
db.student.aggregate([
{
"$project": {
"maths_result": {
"$arrayElemAt": [
{
"$filter": {
"input": "$results",
"as": "res",
"cond": {
"$eq": ["$$res.subject", "maths"]
}
}
},
0
]
}
}
},
{
"$project": {
"maths_fail": { "$lt": ["$maths_result.score", 35 ] }
}
}
])
示例输出
/* 1 */
{
"_id" : 0,
"maths_fail" : true
}
/* 2 */
{
"_id" : 1,
"maths_fail" : false
}
/* 3 */
{
"_id" : 2,
"maths_fail" : true
}
/* 4 */
{
"_id" : 3,
"maths_fail" : false
}
/* 5 */
{
"_id" : 4,
"maths_fail" : true
}
第3步 $group
将所有文档整体分组以汇总计数。总文档计数由表达式"total": { "$sum": 1 }
导出,而条件总和
"$sum": { "$cond": ["$maths_fail", 1, 0 ] }
将为您提供失败的总数:
db.student.aggregate([
{
"$project": {
"maths_result": {
"$arrayElemAt": [
{
"$filter": {
"input": "$results",
"as": "res",
"cond": {
"$eq": ["$$res.subject", "maths"]
}
}
},
0
]
}
}
},
{
"$project": {
"maths_fail": { "$lt": ["$maths_result.score", 35 ] }
}
},
{
"$group": {
"_id": null,
"total": { "$sum": 1 },
"fail_count": { "$sum": { "$cond": ["$maths_fail", 1, 0 ] } }
}
}
])
示例输出
/* 1 */
{
"_id" : null,
"total" : 5,
"fail_count" : 3
}
最后的渠道会使用arithmetic operators $divide
和 $multiply
为您提供百分比:
{
"$project": {
"percentage_maths_fail": {
"$multiply": [
{ "$divide": ["$fail_count", "$total"] },
100
]
}
}
}
最终输出
/* 1 */
{
"_id" : null,
"percentage_maths_fail" : 60
}