定义
兼容性
可以使用 $convert 查找托管在以下环境中的部署:
MongoDB Atlas:用于云中 MongoDB 部署的完全托管服务
MongoDB Enterprise:基于订阅、自我管理的 MongoDB 版本
MongoDB Community:源代码可用、免费使用且可自行管理的 MongoDB 版本
语法
在版本8.3中进行了更改。
{ $convert: { input: <expression>, to: <type expression> || { type: <type expression>, subtype: <int> }, base: <expression>, // new in 8.3 format: <string>, onError: <expression>, onNull: <expression> } }
$convert 接受包含以下字段的文档:
字段 | 必要性 | 说明 | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 必需 | |||||||||||||||||||||||||||||||||||||
| 必需 | 指定将
| ||||||||||||||||||||||||||||||||||||
| 如果将 | 参数可以是任何有效表达式,并能解析为下列数字或字符串标识符之一:
| ||||||||||||||||||||||||||||||||||||
| Optional | 如果
默认值: 0(通用二进制子类型) | ||||||||||||||||||||||||||||||||||||
| Optional | 为 | ||||||||||||||||||||||||||||||||||||
| Optional | 用于在字符串和数字类型之间转换的整数基数。
8.3版本新增。 | ||||||||||||||||||||||||||||||||||||
| 与 | 指定
如果 | ||||||||||||||||||||||||||||||||||||
| Optional | 转换期间出现错误时返回的值,其中包括不支持的类型转换。参数可以是任何有效表达式。 如果未指定,此操作则会在出现错误时引发错误并停止。 | ||||||||||||||||||||||||||||||||||||
| Optional |
除 $convert 外,当默认 "onError" 和 "onNull" 行为可以接受时,MongoDB 还提供以下聚合操作符作为速记:
行为
以下部分介绍如何将值转换为不同类型。
转换为 BinData
从MongoDB 8.1 开始,如果将 input字段设立为以下类型之一,则可以将 to字段设立为 binData:
intlongdouble
从MongoDB 8.1 开始,尝试在不同 binData 子类型之间进行转换时,$convert 会返回错误。在MongoDB 8.0 中,$convert 返回原始值和原始子类型:不执行转换。8.0 之前的MongoDB版本没有 binData 转换。
从数字类型转换为 binData:
将数字类型转换为 binData 时:
int成为 4 字节的binData。long成为 8 字节的binData。double成为 8 字节的binData。
数值输出的 byteOrder 默认为“little”,即最低有效字节在前。相反,“big”会将最高有效字节放在第一位。
将 long 转换为 binData:
输入:
db.t.insertOne( { a: Long(42) } )
db.t.aggregate([ { $project: { _id: 0, convertedBD: { $convert: { input: "$a", to: "binData", } }, } } ])
输出:
[ { convertedBD: Binary.createFromBase64('KgAAAAAAAAA=', 0) } ]
使用大端字节序将 long 转换为 binData:
输入:
db.t.insertOne( { a: Long(42) } )
db.t.aggregate([ { $project: { _id: 0, convertedBD: { $convert: { input: "$a", to: "binData", byteOrder: "big", } }, } } ])
输出:
[ { convertedBD: Binary.createFromBase64('AAAAAAAAACo=', 0), } ]
将 double 转换为 binData:
输入:
db.t.insertOne( { a: Double(42.0) } )
db.t.aggregate([ { $project: { _id: 0, convertedBD: { $convert: { input: "$a", to: "binData", } }, } } ])
输出:
[ { convertedBD: Binary.createFromBase64('AAAAAAAARUA=', 0) } ]
将 int 转换为 binData:
输入:
db.t.insertOne( { a: 42 } )
db.t.aggregate([ { $project: { _id: 0, convertedBD: { $convert: { input: "$a", to: "binData", } }, } } ])
输出:
[ { convertedBD: Binary.createFromBase64('KgAAAA==', 0) } ]
将数值大量转换为 binData:
此示例展示了 $convert 如何将包含不同类型数值的数组转换为 binData。
输入:
db.t.insertMany([ // Empty array { a: [ ] }, // Bool array { a: [ false, true, true, true, true, true, true, true, false, false, false, false, false, true, true, true ] }, // Int array { a: [NumberInt(0), NumberInt(1), NumberInt(0), NumberInt(10)] }, // Double array { a: [ Double(0.0), Double(1.0), Double(0.0), Double(1.0), Double(3.14) ] }, ])
db.t.aggregate([ { $project: { _id: 0, original: "$a", convertedVector: { $convert: { input: "$a", to: { type: "binData" } } } } } ])
输出:
[ { original: [], convertedVector: Binary.fromPackedBits(new Uint8Array([])) }, { original: [ false, true, true, true, true, true, true, true, false, false, false, false, false, true, true, true ], convertedVector: Binary.fromPackedBits(new Uint8Array([ 127, 7 ])) }, { original: [ 0, 1, 0, 10 ], convertedVector: Binary.fromInt8Array(new Int8Array([ 0, 1, 0, 10 ])) }, { original: [ 0, 1, 0, 1, 3.14 ], convertedVector: Binary.fromFloat32Array(new Float32Array([ 0, 1, 0, 1, 3.140000104904175 ])) } ]
从字符串转换为 BinData
MongoDB还支持 binData 和字符串之间的转换。
以下示例演示如何将字符串转换为 binData。
例子 | 结果 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| | |||||||||||
| | |||||||||||
| | |||||||||||
| | |||||||||||
| | |||||||||||
| | |||||||||||
| |
注意
从MongoDB 8.1 开始,尝试在不同 binData 子类型之间进行转换时,$convert 会返回错误。在MongoDB 8.0 中,$convert 返回原始值和原始子类型:不执行转换。8.0 之前的MongoDB版本没有 binData 转换。
转换为数组
8.3版本新增。
下表列出了可转换为大量的输入类型:
输入类型 | 行为 |
|---|---|
BinData | 返回数值大量。 大量元素的数字类型取决于 binData 格式。 |
字符串 | 返回与字符串内容相对应的大量。 |
空值或缺失 | 返回 null。 |
下表列出了字符串到大量转换的部分示例:
例子 | 结果 | ||
|---|---|---|---|
| [ 1, 2, 3 ] | ||
| [ 'a', 'b', 'c' ] | ||
| [ ] | ||
| 错误:输入与预期类型“大量”不匹配 | ||
| 错误:在 $convert 中不支持在没有 onError 值的情况下从 int 到大量的转换 | ||
| 错误:输入不代表有效的JSON:意外的独立运行值 | ||
| [ { '$oid': '507f1f77bcf86cd799439011' } ] | ||
| [ 1, 2, 3 ] 注意
| ||
| 'on error!' | ||
| 'on null!' |
将 binData 转换为数组
此示例展示了 $convert 如何将不同格式的 binData 转换为包含各自类型值的数组:
输入:
db.t.insertMany([ // Empty PACKED_BIT vector converts to empty array { v: BinData(9, "EAA=") }, // PACKED_BIT vector converts to bool array { v: BinData(9, "EAB/Bw==") }, // INT8 vector converts to int array { v: BinData(9, "AwAAAQ==") }, // FLOAT32 vector converts to double array { v: BinData(9, "JwCamZk+") }, // FLOAT32 vector with special values converts to [-Infinity, 0, Infinity] { v: BinData(9, "JwAAAID/AAAAAAAAgH8=") } ])
db.t.aggregate([ { $project: { _id: 0, original: "$v", asArray: { $convert: { input: "$v", to: { type: "array" } } } } } ])
输出:
[ { original: Binary.fromPackedBits(new Uint8Array([])), asArray: [] }, { original: Binary.fromPackedBits(new Uint8Array([ 127, 7 ])), asArray: [ false, true, true, true, true, true, true, true, false, false, false, false, false, true, true, true ] }, { original: Binary.fromInt8Array(new Int8Array([ 0, 1 ])), asArray: [ 0, 1 ] }, { original: Binary.fromFloat32Array(new Float32Array([ 0.30000001192092896 ])), asArray: [ 0.30000001192092896 ] }, { original: Binary.fromFloat32Array(new Float32Array([ -Infinity, 0, Infinity ])), asArray: [ -Infinity, 0, Infinity ] } ]
转换为对象
8.3版本新增。
下表列出了可转换为对象的输入类型:
输入类型 | 行为 |
|---|---|
字符串 | 返回与字符串中的内容相对应的文档。 |
空值或缺失 | 返回 null。 |
下表列出了转换为对象的部分示例:
例子 | 结果 | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| { a: 1, b: 2 } | ||||||||
| { } | ||||||||
| 错误:输入与预期类型“对象”不匹配 | ||||||||
| 错误:输入不代表有效的JSON:意外的独立运行值 | ||||||||
| 错误:输入不代表有效的JSON:非法嵌入空字节 | ||||||||
| { name: 'fox00o' } | ||||||||
| { a: 3, b: 2 } | ||||||||
| { foo: null } | ||||||||
| { foo: false } | ||||||||
| { ['__proto__']: { foo: null } } | ||||||||
| { foo: 'NaN' } | ||||||||
| { foo: 123 } | ||||||||
| { foo: Long('4294967296') } | ||||||||
| { foo: 1.123123 } | ||||||||
| { foo: 1200 } | ||||||||
| { largePos: 18446744073709552000 } | ||||||||
| { largeNeg: -18446744073709552000 } | ||||||||
| null | ||||||||
| { objectId: '507f1f77bcf86cd799439011', uuid: '3b241101-e2bb-4255-8caf-4136c566a962', date: '2018-03-27T16:58:51.538Z', regex: '/^ABC/i', js: 'function (s) {return s + "foo";}', timestamp: 'Timestamp(1565545664, 1)', arr: [ 1, 2, 3 ] } |
转换为布尔值
下表列出了可转换为布尔值的输入类型:
输入类型 | 行为 |
|---|---|
阵列 | 返回 true |
二进制数据 | 返回 true |
布尔 | 不操作。返回布尔值。 |
代码 | 返回 true |
Date | 返回 true |
Decimal 数据类型 | Returns true if not zero Return false if zero |
double | Returns true if not zero Return false if zero |
整型 | Returns true if not zero Return false if zero |
JavaScript | 返回 true |
Long | Returns true if not zero Return false if zero |
Max key | 返回 true |
最小键值 | 返回 true |
null | 返回为 |
对象 | 返回 true |
ObjectId | 返回 true |
正则表达式 | 返回 true |
字符串 | 返回 true |
时间戳 | 返回 true |
要详细了解 MongoDB 中的数据类型,请参阅 BSON 类型。
下表列出了一些转换为布尔值的示例:
例子 | 结果 | ||||
|---|---|---|---|---|---|
| true | ||||
| false | ||||
| true | ||||
| true | ||||
| false | ||||
| true | ||||
| true | ||||
| true | ||||
| true | ||||
| true | ||||
| null |
转换为整数
下表列出了可转换为整数的输入类型:
输入类型 | 行为 |
|---|---|
布尔 | Returns 0 for false.Returns 1 for true. |
BinData | 以整数形式返回
如果 |
double | 返回截断后的值。 截断后的 double 值必须介于整数的最小值与最大值之间。 如果 double 值的截断值小于最小整数值或大于最大整数值,则无法转换该 double 值。 |
Decimal 数据类型 | 返回截断后的值。 截断后的十进制值必须介于整数的最小值与最大值之间。 如果十进制数值的截断值小于最小整数值或大于最大整数值,则无法转换该十进制数值。 |
整型 | 不操作。返回整数值。 |
Long | 以整数形式返回该长整型值。 该长整型值必须介于整数的最小值与最大值范围之间。 不能转换小于最小整数值或大于最大整数值的长整数值。 |
字符串 | 以整数形式返回字符串的数值。 如果省略 如果指定 |
下表列出了转换为整数的部分示例:
例子 | 结果 | |||||
|---|---|---|---|---|---|---|
| 1 | |||||
| 0 | |||||
| 1 | |||||
| 5 | |||||
| 错误 | |||||
| 5000 | |||||
| 错误 | |||||
| -2 | |||||
| 错误 | |||||
| null | |||||
| 1048576 | |||||
| -1763180545 | |||||
| 错误:由于长度 7 无效,无法转换 BinData |
转换为十进制数
下表列出了可转换为十进制值的输入类型:
输入类型 | 行为 |
|---|---|
布尔 | Returns Decimal128( "0" ) for false.Returns Decimal128( "1" ) for true. |
double | 以十进制形式返回 double 值。 |
Decimal 数据类型 | 不操作。返回该十进制数。 |
整型 | 以十进制形式返回该整型值。 |
Long | 以十进制形式返回该长值。 |
字符串 | 以十进制形式返回该字符串的数值。 如果省略 如果指定 |
Date | 返回日期值对应的纪元起的毫秒数。 |
下表列出了转换为十进制值的部分示例:
例子 | 结果 | ||||
|---|---|---|---|---|---|
| Decimal128("1") | ||||
| Decimal128("0") | ||||
| Decimal128("2.50000000000000") | ||||
| Decimal128("5") | ||||
| Decimal128("10000") | ||||
| Decimal128("-5.5") | ||||
| Decimal128("1522039108044") |
转换为 double
下表列出了可转换为 double 的输入类型:
输入类型 | 行为 |
|---|---|
布尔 | Returns NumberDouble(0) for false.Returns NumberDouble(1) for true. |
BinData | 以双精度值形式返回
如果 |
double | 不操作。返回 double。 |
Decimal 数据类型 | 以 double 形式返回该十进制值。 该十进制值必须介于 double 的最小值与最大值范围之间。 如果某一十进制值的值小于最小 double 值或大于最大 double 值,则无法转换该十进制值。 |
整型 | 以 double 形式返回该 int 值。 |
Long | 以 double 形式返回该 long 值。 |
字符串 | 以 double 形式返回该字符串的数值。 如果省略 如果指定 |
Date | 返回日期值对应的纪元起的毫秒数。 |
下表列出了转换为 double 的部分示例:
例子 | 结果 | |||||
|---|---|---|---|---|---|---|
| 1 | |||||
| 0 | |||||
| 2.5 | |||||
| 5 | |||||
| 10000 | |||||
| - 5.5 | |||||
| 50000000000 | |||||
| 1522039108044 | |||||
| 4.814824932714571e-36 | |||||
| 错误:由于长度 2 无效,无法转换 binData |
次正规数
从MongoDB8.3 开始,服务器能够解析所有可表示的双精度点的全范围。这包括最高有效数字有前导零且指数具有最小可能值的次正规数。有关详细信息,请参阅次正规数 。
在MongoDB的早期版本中,当您尝试解析这些数字时,服务器会返回错误。以下示例会在MongoDB 8.3 之前的版本中引发错误:
db.t.insertOne( { v: "7.08263e-317" } ) db.t.aggregate([ { $project: { converted: { $convert: { input: "$v", to: "double" }, } } } ])
此示例失败并出现类似以下内容的错误:
MongoServerError[ConversionFailure]: Executor error during aggregate command on namespace: test.t :: caused by :: Failed to parse number '7.08263e-317' in $convert with no onError value: Out of range
转换为长整型
下表列出了可转换为长整型的输入类型:
输入类型 | 行为 |
|---|---|
布尔 | Returns 0 for false.Returns 1 for true. |
BinData | 以长整型形式返回
如果 |
double | 返回截断后的值。 截断后的 double 值必须介于长整型值的最小值与最大值之间。 如果 double 值的截断值小于最小长值或大于最大长值,则无法转换该 double 值。 |
Decimal 数据类型 | 返回截断后的值。 截断后的十进制值必须介于长整型值的最小值与最大值之间。 如果某一十进制数值的截断值小于最小长整型值或大于最大长整型值,则无法转换该十进制数值。 |
整型 | 以 long 形式返回整数值。 |
Long | 不操作。返回长整型值。 |
字符串 | 返回字符串的数值。 如果省略 如果指定 |
Date | 将“日期”转换为自纪元起的毫秒数。 |
下表列出了转换为长整型值的部分示例:
例子 | 结果 | |||||
|---|---|---|---|---|---|---|
| Long("1") | |||||
| Long("0") | |||||
| Long("2") | |||||
| Long("5") | |||||
| 错误 | |||||
| Long("8") | |||||
| Long("1522039108044") | |||||
| Long("2") | |||||
| 错误 | |||||
| null | |||||
| Long("1048576") |
转换为日期
下表列出了可转换为日期的输入类型:
输入类型 | 行为 |
|---|---|
double | 返回与截断后的由 double 值表示的毫秒数相对应的日期。 正数对应于 1970 年 1 月 1 日以来的毫秒数。 负数对应于 1970 年 1 月 1 日之前的毫秒数。 |
Decimal 数据类型 | 返回与由截断后的十进制值表示的毫秒数相对应的日期。 正数对应于 1970 年 1 月 1 日以来的毫秒数。 负数对应于 1970 年 1 月 1 日之前的毫秒数。 |
Long | 返回与该长值表示的毫秒数相对应的日期。 正数对应于 1970 年 1 月 1 日以来的毫秒数。 负数对应于 1970 年 1 月 1 日之前的毫秒数。 |
字符串 | 返回与日期字符串相对应的日期。 该字符串必须为有效的日期字符串,例如:
|
ObjectId | 返回与对象标识符的时间戳对应的日期。 |
时间戳 | 返回与时间戳相对应的日期。 |
下表列出了转换为日期的部分示例:
例子 | 结果 | ||||
|---|---|---|---|---|---|
| ISODate("1973-10-20T21:20:00.000Z") | ||||
| ISODate("2009-09-19T14:53:56.000Z") | ||||
| ISODate("2004-11-09T11:33:20.000Z") | ||||
| ISODate("1935-02-22T12:26:40.000Z") | ||||
| ISODate("2018-03-27T04:08:58.000Z") | ||||
| ISODate("2018-03-03T00:00:00.000Z") | ||||
| ISODate("2018-03-20T06:00:06.000Z") | ||||
| 错误 | ||||
| ISODate("2021-11-23T17:21:58.000Z") |
转换为 ObjectId
下表列出可以转换为对象标识符的输入类型:
输入类型 | 行为 |
|---|---|
字符串 | 以长度为 24 的 16 进制字符串返回对象标识符。 不能转换不是长度 24 的十六进制字符串的字符串值。 |
下表列出了转换为日期的部分示例:
例子 | 结果 | ||||
|---|---|---|---|---|---|
| ObjectId("5ab9cbfa31c2ab715d42129e") | ||||
| 错误 |
转换为字符串
下表列出了可转换为字符串的输入类型:
输入类型 | 行为 |
|---|---|
阵列 | 以字符串形式返回 8.3版本新增。 |
BinData | 如果 |
布尔 | 以字符串形式返回布尔值。 |
Date | 以字符串形式返回 |
Decimal 数据类型 |
|
double |
|
整型 |
|
Long |
|
Max key | 以字符串形式返回 8.3版本新增。 |
最小键值 | 以字符串形式返回 8.3版本新增。 |
对象 | 以字符串形式返回该对象。 8.3版本新增。 |
ObjectId | 以十六进制字符串形式返回 |
正则表达式 | 以字符串形式返回 8.3版本新增。 |
字符串 | 无需操作。返回字符串值。 |
时间戳 | 以字符串形式返回 8.3版本新增。 |
注意
下表列出了转换为字符串的部分示例:
例子 | 结果 | ||||||
|---|---|---|---|---|---|---|---|
| "true" | ||||||
| "false" | ||||||
| "2.5" | ||||||
| "2" | ||||||
| "1000" | ||||||
| "5ab9c3da31c2ab715d421285" | ||||||
| "2018-03-27T16:58:51.538Z" | ||||||
| 'hn3f' | ||||||
| "invalid" |
示例
基数转换示例
使用占位符文档创建集合examples:
db.examples.insertOne({ _id: 1 })
以下示例使用不同进制在数字和字符串之间进行转换:
db.examples.aggregate([ { $project: { _id: 0, bin: { $convert: { input: 10, to: "string", base: 2 } }, hex: { $convert: { input: 10, to: "string", base: 16 } }, intFromBin: { $convert: { input: "1010", to: "int", base: 2 } }, intFromHex: { $convert: { input: "A", to: "int", base: 16 } } } } ])
此操作返回以下文档:
{ bin: "1010", hex: "A", intFromBin: 10, intFromHex: 10 }
类型转换示例
使用以下文档创建集合 orders:
db.orders.insertMany( [ { _id: 1, item: "apple", qty: 5, price: 10 }, { _id: 2, item: "pie", qty: 10, price: Decimal128("20.0") }, { _id: 3, item: "ice cream", qty: 2, price: "4.99" }, { _id: 4, item: "almonds" }, { _id: 5, item: "bananas", qty: 5000000000, price: Decimal128("1.25") } ] )
对 orders 集合执行的以下聚合操作会将 price 转换为十进制值:
// Define stage to add convertedPrice and convertedQty fields with // the converted price and qty values. // If price or qty values are missing, the conversion returns a // value of decimal value or int value of 0. // If price or qty values cannot be converted, the conversion returns // a string priceQtyConversionStage = { $addFields: { convertedPrice: { $convert: { input: "$price", to: "decimal", onError: "Error", onNull: Decimal128("0") } }, convertedQty: { $convert: { input: "$qty", to: "int", onError:{ $concat: [ "Could not convert ", { $toString:"$qty" }, " to type integer." ] }, onNull: Int32("0") } }, } }; totalPriceCalculationStage = { $project: { totalPrice: { $switch: { branches: [ { case: { $eq: [ { $type: "$convertedPrice" }, "string" ] }, then: "NaN" }, { case: { $eq: [ { $type: "$convertedQty" }, "string" ] }, then: "NaN" }, ], default: { $multiply: [ "$convertedPrice", "$convertedQty" ] } } } } }; db.orders.aggregate( [ priceQtyConversionStage, totalPriceCalculationStage ])
该操作将返回以下文档:
{ _id: 1, totalPrice: Decimal128("50") }, { _id: 2, totalPrice: Decimal128("200.0") }, { _id: 3, totalPrice: Decimal128("9.98") }, { _id: 4, totalPrice: Decimal128("0") }, { _id: 5, totalPrice: 'NaN' }
了解详情
使用以下命令将值转换为大量:
$toArray将字符串转换为对象
$toObject将值转换为布尔值
$toBool使用以下命令将值转换为整数:
$toInt使用以下命令将值转换为十进制:
$toDecimal使用以下命令将值转换为双精度值:
$toDouble将值转换为长整型值
$toLong使用以下命令将值转换为日期:
$toDate使用以下命令将值转换为 ObjectId:
$toObjectId将值转换为字符串
$toString将日期字符串转换为日期对象
$dateFromString将日期对象转换为字符串
$dateToString