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
}
相关推荐
qq_246839753 分钟前
postgresql xxhash64 哈希函数实现
数据库·postgresql·哈希算法
希望奇迹很安静3 分钟前
等级保护测评
网络·数据库
会博通·代码搬运工14 分钟前
疾控档案落地难点:异构业务系统并存,高价值纸质凭证如何回流业务闭环
数据库·档案管理·档案管理系统·智能扫描设备·会博通
数智启示录16 分钟前
Apache Kafka Consumer 扩到 40 个仍不提速:Partition 上限锁死有效并行度 【Kafka合集】
数据库·经验分享·分布式·缓存·面试·kafka·apache
数智启示录23 分钟前
Apache Kafka 幂等 Producer 的边界:Exactly-Once 到了 MySQL 为什么失效 【Kafka合集】
数据库·经验分享·分布式·mysql·面试·kafka·apache
Java小白笔记25 分钟前
Java 实现阿里云 OSS 文件上传链路:普通上传、秒传、分片与断点续传
java·开发语言·数据库·spring·阿里云
—Miss. Z—26 分钟前
计算机三级数据库技术—填空题
数据库·mysql
数智启示录1 小时前
Apache Kafka 同 Key 仍会乱序:从分区 Offset 到业务可见的四道边界 【Kafka 合集】
大数据·数据库·经验分享·分布式·面试·kafka·apache
烬羽1 小时前
给 Agent 一个检索式记忆:把对话历史存进 Milvus,该记的都记得
javascript·数据库·agent
星云API技术支持1 小时前
企业微信二次开发外部群:群聊数据与联系人信息如何建立关联
数据库·php·企业微信