定义
兼容性
可以使用 $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 接受包含以下字段的文档:
字段 | 必要性 | 说明 |
|---|---|---|
| 必需 | 参数可以是任何有效的表达式。有关表达式的更多信息,请参阅表达式。 从MongoDB 8.1 开始,如果将
从 MongoDB 8.3 开始,如果 将值转换为 从 MongoDB 9.0 开始,如果 |
| 必需 | 指定将
|
| 如果将 | |
| Optional | 如果 |
| Optional | 为 |
| Optional | 用于在 string 和数字类型之间转换的整数基数。
8.3版本新增。 |
| 与 | 指定
如果 |
| Optional | 转换期间出现错误时返回的值,其中包括不支持的类型转换。参数可以是任何有效表达式。 如果未指定,此操作则会在出现错误时引发错误并停止。 |
| Optional |
除 $convert 外,当默认 "onError" 和 "onNull" 行为可以接受时,MongoDB 还提供以下聚合操作符作为速记:
类型标识符
to.type 字段接受以下数字和 string 标识符:
字符串标识符 | 数字标识符 | 注意 |
|---|---|---|
"double" | 1 | 请参阅 转换为 double。 |
"string" | 2 | 请参阅转换为字符串。 |
"object" | 3 | 请参阅 转换为对象。 |
"array" | 4 | 请参阅转换为数组。 |
"binData" | 5 | 请参阅 转换为 BinData。 |
"objectId" | 7 | 请参阅 转换为 ObjectId。 |
"bool" | 8 | 请参阅转换为布尔值。 |
"date" | 9 | 请参阅转换为日期。 |
"int" | 16 | 请参阅 转换为整数。 |
"long" | 18 | 请参阅转换为长整型。 |
"decimal" | 19 | 请参阅 转换为十进制数。 |
二进制子类型
下表列出 to.subtype 字段的有效值:
数值 | 说明 |
|---|---|
0 | 通用二进制子类型 |
1 | 函数数据 |
2 | 二进制(旧版) |
3 | UUID(旧) |
4 | UUID |
5 | MD5 |
6 | 加密的 BSON 值 |
7 | 压缩时间序列数据 5.2版本新增。 |
8 | 敏感数据,例如密钥或密码。 MongoDB 不会记录子类型为 8 的二进制数据的字面值。相反,MongoDB 会记录占位符值 |
9 | 向量数据是由相同类型的数字组成的密集数组。 |
128 | 自定义数据 |
行为
以下部分介绍如何将值转换为不同类型。
转换为 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
9.0版本新增。
当 input 字段解析为对象且 to 字段为 binData 时,$convert 将返回该对象的原始 BSON 表示形式。除非您在 to.subtype 中指定了其他值,否则返回的 binData 值的子类型为 0。
由于输出是对象的原始 BSON,因此对象字段的顺序及其数组中元素的顺序都会影响返回的字节。
$convert 验证此转换的 format、byteOrder 和 base 字段,但这些字段对输出没有影响。
下表显示了对象到 binData 的转换示例:
例子 | 结果 |
|---|---|
| |
| |
| |
| 输出与前面的示例不同,因为字段顺序不同。 |
| |
| 输出与前面的示例不同,因为数组元素的顺序不同。 |
| |
|
|
| Error: Invalid 'format' argument for $convert: bson
|
| null |
从字符串转换为 BinData
MongoDB还支持 binData 和字符串之间的转换。
以下示例演示如何将字符串转换为 binData。
例子 | 结果 |
|---|---|
| |
| |
| |
| |
| |
| |
| |
注意
从MongoDB 8.1 开始,尝试在不同 binData 子类型之间进行转换时,$convert 会返回错误。在MongoDB 8.0 中,$convert 返回原始值和原始子类型:不执行转换。8.0 之前的MongoDB版本没有 binData 转换。
转换为数组
8.3版本新增。
下表列出了可转换为数组的input类型:
输入类型 | 行为 |
|---|---|
BinData | 返回数值数组。 数组元素的数字类型取决于 binData 格式。 |
字符串 | 返回与内容在 string 中的数组。 该字符串必须包含表示有效JSON数组的字符。 |
空值或缺失 | 返回 null。 |
下表列出了 string 到数组转换的部分示例:
例子 | 结果 |
|---|---|
| [ 1, 2, 3 ] |
| [ 'a', 'b', 'c' ] |
| [ ] |
| 错误:input 不匹配预期类型“数组” |
| 错误:在 $convert 中不支持在没有 onError 值的情况下从 int 到数组的转换 |
| 错误:input不代表有效的JSON:意外的独立运行的实例值 |
| [ { '$oid': '507f1f77bcf86cd799439011' } ] |
| [ 1, 2, 3 ] |
| 'on error!' |
| 'on null!' |
将 binData 转换为数组
此示例展示了 $convert 如何将不同格式的 binData 转换为包含各自类型值的数组:
input:
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版本新增。
下表列出了可转换为对象的 input 类型:
输入类型 | 行为 |
|---|---|
字符串 | 返回与 string 中的内容相对应的 document。 该字符串必须包含表示有效JSON对象的字符。 |
空值或缺失 | 返回 null。 |
下表列出了转换为对象的部分示例:
例子 | 结果 |
|---|---|
| { a: 1, b: 2 } |
| { } |
| 错误:input与预期类型“对象”不匹配 |
| 错误:input不代表有效的JSON:意外的独立运行的实例值 |
| 错误:input不代表有效的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 |
| { |
转换为布尔值
下表列出了可转换为布尔值的输入类型:
输入类型 | 行为 |
|---|---|
阵列 | 返回 true |
二进制数据 | 返回 true |
布尔 | 不操作。返回布尔值。 |
代码 | 返回 true |
Date | 返回 true |
Decimal 数据类型 | 如果不为零,返回 true |
double | 如果不为零,返回 true |
整型 | 如果不为零,返回 true |
JavaScript | 返回 true |
Long | 如果不为零,返回 true |
Max key | 返回 true |
最小键值 | 返回 true |
null | 返回为 |
对象 | 返回 true |
ObjectId | 返回 true |
正则表达式 | 返回 true |
字符串 | 返回 true |
时间戳 | 返回 true |
要详细了解 MongoDB 中的数据类型,请参阅 MongoDB BSON types。
下表列出了一些转换为布尔值的示例:
例子 | 结果 |
|---|---|
| true |
| false |
| true |
| true |
| false |
| true |
| true |
| true |
| true |
| true |
| null |
转换为整数
下表列出了可转换为整数的输入类型:
输入类型 | 行为 |
|---|---|
布尔 | 返回 |
BinData | 以整数形式返回
如果 |
double | 返回截断后的值。 截断后的 double 值必须介于整数的最小值与最大值之间。 如果 double 值的截断值小于最小整数值或大于最大整数值,则无法转换该 double 值。 |
Decimal 数据类型 | 返回截断后的值。 截断后的十进制值必须介于整数的最小值与最大值之间。 如果十进制数值的截断值小于最小整数值或大于最大整数值,则无法转换该十进制数值。 |
整型 | 不操作。返回整数值。 |
Long | 以整数形式返回该长整型值。 该长整型值必须介于整数的最小值与最大值范围之间。 不能转换小于最小整数值或大于最大整数值的长整数值。 |
字符串 | 以整数形式返回字符串的数值。 如果省略 如果指定 |
下表列出了转换为整数的部分示例:
例子 | 结果 |
|---|---|
| 1 |
| 0 |
| 1 |
| 5 |
| 错误 |
| 5000 |
| 错误 |
| -2 |
| 错误 |
| null |
| 1048576 |
| -1763180545 |
| 错误:由于长度 7 无效,无法转换 BinData |
转换为十进制数
下表列出了可转换为十进制值的输入类型:
输入类型 | 行为 |
|---|---|
布尔 | 返回 |
double | 以十进制形式返回 double 值。 |
Decimal 数据类型 | 不操作。返回该十进制数。 |
整型 | 以十进制形式返回该整型值。 |
Long | 以十进制形式返回该长值。 |
字符串 | 以十进制形式返回该字符串的数值。 如果省略 如果指定 |
Date | 返回日期值对应的纪元起的毫秒数。 |
下表列出了转换为十进制值的部分示例:
例子 | 结果 |
|---|---|
| Decimal128("1") |
| Decimal128("0") |
| Decimal128("2.50000000000000") |
| Decimal128("5") |
| Decimal128("10000") |
| Decimal128("-5.5") |
| Decimal128("1522039108044") |
转换为 double
下表列出了可转换为 double 的输入类型:
输入类型 | 行为 |
|---|---|
布尔 | 返回 NumberDouble(0) 以表示 |
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 |
次正规数
从MongoDB 8.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转换为长整型
下表列出了可转换为长整型的输入类型:
输入类型 | 行为 |
|---|---|
布尔 | 返回 |
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") |
| 错误 |
转换为字符串
下表列出了可转换为字符串的输入类型:
输入类型 | 行为 |
|---|---|
阵列 | Returns the 8.3版本新增。 |
BinData | 如果 |
布尔 | 以字符串形式返回该布尔值。 |
Date | Returns the |
Decimal 数据类型 | 以 string 形式返回 |
double | 以 string 形式返回 |
整型 | 以 string 形式返回 |
Long | 以 string 形式返回 |
Max key | Returns the 8.3版本新增。 |
最小键值 | Returns the 8.3版本新增。 |
对象 | 以 string 形式返回该对象。 8.3版本新增。 |
ObjectId | 以十六进制字符串形式返回 |
正则表达式 | Returns the 8.3版本新增。 |
字符串 | 无需操作。返回 string 值。 |
时间戳 | Returns the 8.3版本新增。 |
注意
当您指定 base 且 input 为数值类型时,$convert 会返回以该基数表示的整数值的 string 表示形式。字符串的基数转换仅支持针对整数值,否则,除非指定 onError,否则 $convert 会返回转换错误。
下表列出了转换为字符串的部分示例:
例子 | 结果 |
|---|---|
| "true" |
| "false" |
| "2.5" |
| "2" |
| "1000" |
| "5ab9c3da31c2ab715d421285" |
| "2018-03-27T16:58:51.538Z" |
| 'hn3f' |
| "invalid" |
示例
本页上的示例使用来自 sample_mflix 数据集的数据。有关如何将此数据集加载到您的自管理 MongoDB 部署中的详细信息,请参阅 加载示例数据集。如果您对示例数据库进行了任何修改,您可能需要删除并重新创建数据库,才能运行此页面上的示例。
基数转换示例
十六进制字符串是一种表示整数的紧凑方式,许多系统将标识符作为十六进制值进行交换。以下示例将每部电影的数字 imdb.id 转换为十六进制字符串:
db.movies.aggregate( [ { $match: { title: { $in: [ "The Godfather", "Toy Story", "Metropolis" ] } } }, { $sort: { title: 1 } }, { $project: { _id: 0, title: 1, imdbId: "$imdb.id", hexId: { $convert: { input: "$imdb.id", to: "string", base: 16 } } } }] )[ { title: 'Metropolis', imdbId: 293416, hexId: '47A28' }, { title: 'The Godfather', imdbId: 68646, hexId: '10C26' }, { title: 'Toy Story', imdbId: 114709, hexId: '1C015' }]要将十六进制字符串转换回整数,请将该字符串传递给 $convert,并使用 base: 16 和 to: "int"。
类型转换示例
以下聚合操作将 imdb.rating 字段转换为 double,该字段在大多数文档中是 double,但在其他文档中是空字符串。它还将 metacritic 字段(某些文档中缺少该字段)转换为整数。$match 阶段选择了三部电影来说明每种转换结果:
db.movies.aggregate( [ { $match: { title: { $in: [ "The Danish Girl", "The Godfather", "Gertie the Dinosaur" ] } } }, { $project: { _id: 0, title: 1, rating: { $convert: { input: "$imdb.rating", to: "double", onError: "Error", onNull: 0 } }, metacritic: { $convert: { input: "$metacritic", to: "int", onError: "Error", onNull: 0 } } } }, { $sort: { title: 1 } }] )[ { title: 'Gertie the Dinosaur', rating: 7.3, metacritic: 0 }, { title: 'The Danish Girl', rating: 'Error', metacritic: 0 }, { title: 'The Godfather', rating: 9.2, metacritic: 100 }]对于 The Danish Girl,imdb.rating 中的空 string 无法转换为 double,因此 onError 返回 "Error"。对于 Gertie the Dinosaur 和 The Danish Girl,缺少 metacritic,因此 onNull 返回 0。
了解详情
使用以下命令将值转换为数组:
$toArray将 string 转换为对象
$toObject将值转换为布尔值
$toBool使用以下命令将值转换为整数:
$toInt使用以下命令将值转换为十进制:
$toDecimal使用以下命令将值转换为双精度值:
$toDouble将值转换为长整型值
$toLong使用以下命令将值转换为日期:
$toDate使用以下命令将值转换为 ObjectId:
$toObjectId将值转换为 string
$toString将日期 string 转换为日期对象
$dateFromString将日期对象转换为 string
$dateToString