Mongodb聚合操作$isNumber

又是mongodb集合的不强制文档具有相同一致的结构产生的问题。Mongodb这种特点,确实带来了灵活强大的优势,但Mongodb的一些操作符和特性看起来在为这种灵活的结构买单。

这次有两个问题。某一个气温监控系统,采用了不同的传感器厂家生产的系统,不同厂家返回的温度数据有不同的类型,有数字类型的,有字符类型的。还有的传感器损坏,返回来了空数据。

另外一个问题是学生在学校考试当中取得的成绩。不同课程成绩按照不同的录入方式进入到系统。有的按照分数评级,录入了ABCDF这五个等级。而有的课程录入了学生绩点。现在到了评奖学籍的时候,要计算学生成绩绩点的平均值。这个为难坏了工程师。

Mongodb聚合操作用,方法$isNumber来判断字段值或表达式的返回值是否为数字类型。

定义

isNumber,判断指定表达式返回值的类型是否是数字类型。若返回数据类型是Integer, Decimal, Double, Long当中的一种,isNumber返回true,其他的非数字类型,null或文档没有该字段,则返回false。

$isNumber使用下面的语法来判断表达式的值。其中expression是任何一个可用的表达式。

{$isNumber: <expression>}

应用

判断字段值是否为数字类型

有一个传感器表格,记录了下面的信息。其中reading字段中有各种数据类型。

db.sensors.insertMany([
    {"_id": 1, "reading": NumberDecimal("26.0") },
    {"_id": 2, "reading": NumberLong(25.0) },
    {"_id": 3, "reading": NumberInt(24) },
    {"_id": 4, "reading": 24.0 },
    {"_id": 5, "reading": "24" },
    {"_id": 6, "reading": [ NumberDecimal(26)] }
])

使用聚合查询,为查询结果添加新字段isNumber, 并返回reading字段的类型

db.sensors.aggregate([{
    $addFields: { //在聚合查询中添加新字段isNumber和type
        isNumber: {$isNumber: "$reading"}, //判断reading字段是否为数字类型
        type: {$type: "$reading"}
    }
}])

/* 1 */
{
	"_id" : 1,
	"reading" : Decimal128("26.0"),
	"isNumber" : true,
	"type" : "decimal"
},

/* 2 */
{
	"_id" : 2,
	"reading" : Long("25"),
	"isNumber" : true,
	"type" : "long"
},

/* 3 */
{
	"_id" : 3,
	"reading" : 24,
	"isNumber" : true,
	"type" : "int"
},

/* 4 */
{
	"_id" : 4,
	"reading" : 24,
	"isNumber" : true,
	"type" : "int"
},

/* 5 */
{
	"_id" : 5,
	"reading" : "24",
	"isNumber" : false,
	"type" : "string"
},

/* 6 */
{
	"_id" : 6,
	"reading" : [ Decimal128("26") ],
	"isNumber" : false,
	"type" : "array"
}

依据$isNumber的结果修改返回字段值

学生成绩表grade中包含了学生成绩信息。 其中grade字段保存了两种数据类型,一种是字符类型的ABCDF,另一种数字类型的绩点成绩。

db.grades.insertMany([{
    "student_id": 457864153,
    "class_id": "M044",
    "class_desc": "Introduction to MongoDB 4.4",
    "grade": "A"
},{
    "student_id": 457864153,
    "class_id": "M103",
    "class_desc": "Basic Cluster Administration",
    "grade": 3.0
},{
    "student_id": 978451637,
    "class_id": "M320",
    "class_desc": "MongoDB data Modeling",
    "grade": "C"
},{
    "student_id": 978451637,
    "class_id": "M001",
    "class_desc": "MongoDB Basics",
    "grade": 4.0
}])

现在需要计算两个学生的平均绩点。

  • 为查询结果添加新字段points表示学生的绩点

  • 使用$isNumber判断grade字段是否为数字类型,当为数字类型是,直接返回给points字段,如果不是数字类型, 按照等级对应关系返回给points字段。 A-4.0,B-3.0,C-2.0,D-1.0,F-0.0.

    db.grades.aggregate([{
    $addFields: {
    "points": {
    cond: { if: {isNumber: "grade" }, then: "grade",
    else: {
    switch: { branches: [ { case: {eq: ["grade","A"]}, then: 4.0 }, { case: {eq: ["grade","B"]}, then: 3.0 }, { case: {eq: ["grade","C"]}, then: 2.0 }, { case: {eq: ["grade","D"]}, then: 1.0 }, { case: {eq: ["$grade","F"]}, then: 0.0 },
    ]
    }
    }
    }
    }
    }
    },{
    group: { _id: "student_id",
    GPA: {
    avg: "points"
    }
    }
    }])

运行聚合查询,返回结果

/* 1 */
{
	"_id" : 978451637,
	"GPA" : Double("3")
},

/* 2 */
{
	"_id" : 457864153,
	"GPA" : 3.5
}
相关推荐
夜泉_ly2 小时前
MySQL -安装与初识
数据库·mysql
qq_529835353 小时前
对计算机中缓存的理解和使用Redis作为缓存
数据库·redis·缓存
月光水岸New5 小时前
Ubuntu 中建的mysql数据库使用Navicat for MySQL连接不上
数据库·mysql·ubuntu
狄加山6755 小时前
数据库基础1
数据库
我爱松子鱼5 小时前
mysql之规则优化器RBO
数据库·mysql
chengooooooo5 小时前
苍穹外卖day8 地址上传 用户下单 订单支付
java·服务器·数据库
Rverdoser6 小时前
【SQL】多表查询案例
数据库·sql
Galeoto7 小时前
how to export a table in sqlite, and import into another
数据库·sqlite
人间打气筒(Ada)7 小时前
MySQL主从架构
服务器·数据库·mysql
leegong231117 小时前
学习PostgreSQL专家认证
数据库·学习·postgresql