MongoDB从入门到实战(十三):MongoDB 聚合数据类型转换$convert

x33g5p2x  于2021-12-25 转载在 Go  
字(6.0k)|赞(0)|评价(0)|浏览(616)

MongoDB同一个集合中的文档不要求字段一致,也可以是完全不同的,同一个字段的值的数据类型也可以是不同的,如果想将某个字段的不同类型的值都统一处理成同一种类型的值就可以使用数据类型转换,数据类型转换是通过聚合函数aggregate来实现的。

MongoDB4.0增加了一个新的聚合操作符:$convert,用来进行数据类型的转换。这个类型转换操作符简化了数据的抽取、转换和加载的过程。同时将客户端的处理数据的压力转移到了服务器端。从而减轻了客户端处理数据的压力。

// 插入6条数据,其中每条数据的time字段都有些不同,
// 有的是没有这个字段,有的是Date类型,有的是数值类型时间戳,有的甚至是非法的非日期的文本字符串
rs:PRIMARY> var one = {"from":"a","to":"b","money":100};
rs:PRIMARY> var two = {"from":"a","to":"b","money":200,"time":ISODate("2018-05-11T13:58:51.122Z")};
rs:PRIMARY> var thr = {"from":"a","to":"b","money":300,"time":"2018-07-10 14:38:50"};
rs:PRIMARY> var four = {"from":"a","to":"b","money":100,"time":"2017-04-16 14:38:50"};
rs:PRIMARY> var five = {"from":"a","to":"b","money":500,"time":1569569092514};
rs:PRIMARY> var six = {"from":"a","to":"b","money":500,"time":"Last Friday"};
rs:PRIMARY> db.transfer.insertMany([one,two,thr,four,five,six]);
{
	"acknowledged" : true,
	"insertedIds" : [
		ObjectId("60768833c83116b2c09bb433"),
		ObjectId("60768833c83116b2c09bb434"),
		ObjectId("60768833c83116b2c09bb435"),
		ObjectId("60768833c83116b2c09bb436"),
		ObjectId("60768833c83116b2c09bb437"),
		ObjectId("60768833c83116b2c09bb438")
	]
}

定义一个js文件(mongodb-4.4.5/aggregate.js),将要在shell写的命令先在.js文件中先书写好,多行命令在shell中输入体验非常不好。$project是aggregate()函数中的投射,主要用于处理字段的显示或者对字段的处理

conversionStage = {
    // 聚合通道
    $project: {
        // 在数据映射通道中保留原来的数据项,设置为1
        from: 1,
        to: 1,
        money: 1,
        time: {// 转账时间需要做一些类型的转换
            // 转换操作符
            $convert: {
                // 必须书写的 原来的转账时间
                input:"$time",
                // 必须书写的 希望把这一项数据转换哪种类型,date就是mongo的标准时间类型ISODate
                to:"date",
                // onError这一项是可选的。对于存在的属性,但是属性值是完全没有办法转换为标准的日期格式,可以对其显示
                onError: {
                	// $concat表示字段拼接操作符
                    $concat:["can not convert ",{$toString:"$time"}," to date type"]
                },
                // 缺失转账时间这一项,可以对其提示
                onNull:"missing time"
            }
        }
    }
};
// load 函数就是加载js文件到shell中并执行
// 注意:加载文件所在的位置要和启动mongo命令所在的目录要保持一致
rs:PRIMARY> load("aggregate.js")

// 查看定义的变量值
rs:PRIMARY> conversionStage

// 将time字段的值统一转换为date数据类型
rs:PRIMARY> db.transfer.aggregate([conversionStage])
{ "_id" : ObjectId("60768833c83116b2c09bb433"), "from" : "a", "to" : "b", "money" : 100, "time" : "missing time" }
{ "_id" : ObjectId("60768833c83116b2c09bb434"), "from" : "a", "to" : "b", "money" : 200, "time" : ISODate("2018-05-11T13:58:51.122Z") }
{ "_id" : ObjectId("60768833c83116b2c09bb435"), "from" : "a", "to" : "b", "money" : 300, "time" : ISODate("2018-07-10T14:38:50Z") }
{ "_id" : ObjectId("60768833c83116b2c09bb436"), "from" : "a", "to" : "b", "money" : 100, "time" : ISODate("2017-04-16T14:38:50Z") }
{ "_id" : ObjectId("60768833c83116b2c09bb437"), "from" : "a", "to" : "b", "money" : 500, "time" : ISODate("2019-09-27T07:24:52.514Z") }
{ "_id" : ObjectId("60768833c83116b2c09bb438"), "from" : "a", "to" : "b", "money" : 500, "time" : "can not convert Last Friday to date type" }

// aggregate 只是对查询出来的数据进行处理,并不更改原始数据
rs:PRIMARY> db.transfer.find()
{ "_id" : ObjectId("60768833c83116b2c09bb433"), "from" : "a", "to" : "b", "money" : 100 }
{ "_id" : ObjectId("60768833c83116b2c09bb434"), "from" : "a", "to" : "b", "money" : 200, "time" : ISODate("2018-05-11T13:58:51.122Z") }
{ "_id" : ObjectId("60768833c83116b2c09bb435"), "from" : "a", "to" : "b", "money" : 300, "time" : "2018-07-10 14:38:50" }
{ "_id" : ObjectId("60768833c83116b2c09bb436"), "from" : "a", "to" : "b", "money" : 100, "time" : "2017-04-16 14:38:50" }
{ "_id" : ObjectId("60768833c83116b2c09bb437"), "from" : "a", "to" : "b", "money" : 500, "time" : 1569569092514 }
{ "_id" : ObjectId("60768833c83116b2c09bb438"), "from" : "a", "to" : "b", "money" : 500, "time" : "Last Friday" }

将变量filterStage放入到aggregate.js文件中,然后重新加载到shell中。

filterStage = {
   $match: {
         // 选择类型是date类型的数据,不是date的例如字符串类型直接过滤掉
         time:{"$type":"date"}
   }
};
rs:PRIMARY> load("aggregate.js")
rs:PRIMARY> db.transfer.aggregate([conversionStage])
// 先对time字段类型转换,然后再根据类型过滤不是date类型字段的记录,
// 就拿到了所有包含time字段并且时间格式统一的文档了。
rs:PRIMARY> db.transfer.aggregate([conversionStage,filterStage]);
{ "_id" : ObjectId("60768833c83116b2c09bb434"), "from" : "a", "to" : "b", "money" : 200, "time" : ISODate("2018-05-11T13:58:51.122Z") }
{ "_id" : ObjectId("60768833c83116b2c09bb435"), "from" : "a", "to" : "b", "money" : 300, "time" : ISODate("2018-07-10T14:38:50Z") }
{ "_id" : ObjectId("60768833c83116b2c09bb436"), "from" : "a", "to" : "b", "money" : 100, "time" : ISODate("2017-04-16T14:38:50Z") }
{ "_id" : ObjectId("60768833c83116b2c09bb437"), "from" : "a", "to" : "b", "money" : 500, "time" : ISODate("2019-09-27T07:24:52.514Z") }

相关文章