MongoDB中的数据类型转换
我在MongoDB中有一个名为Document的集合。此集合中的文档有一个名为CreationDate的字段,该字段以ISO日期类型存储。我的任务是计算每天创建的文档数量,并按数量异步排序。输出格式必须是 [{u id:'yyyy-MM-dd',cnt:x}]。我尝试使用聚合框架,如下所示MongoDB中的数据类型转换,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我在MongoDB中有一个名为Document的集合。此集合中的文档有一个名为CreationDate的字段,该字段以ISO日期类型存储。我的任务是计算每天创建的文档数量,并按数量异步排序。输出格式必须是 [{u id:'yyyy-MM-dd',cnt:x}]。我尝试使用聚合框架,如下所示 db.Document.aggregate( , {$project: {_id:1, Year:{$year:'$CreationDate'}, Month:{$month:'$CreationD
db.Document.aggregate(
, {$project: {_id:1, Year:{$year:'$CreationDate'}, Month:{$month:'$CreationDate'}, Date:{$dayOfMonth:'$CreationDate'}}}
, {$group: {_id:{$concat:['$Year', '-', '$Month', '-', '$Date']}, cnt:{$sum:1}}}
, {$sort:{'cnt':-1}}
);
代码给出的错误如下:
$concat only supports strings, not NumberInt32
我理解这是因为$year、$month和$dayOfMonth都是返回号码。可以将_id字段组成一个对象,并在应用程序级别将其重新格式化为所需的格式
但从技术角度来看,我有两个问题:
db.Document.aggregate([
{“$group”:{
“_id”:{
“$concat”:[
{“$substr”:[{“$year”:“$CreationDate”},0,4]},
"-",
{“$cond”:[
{“$gt”:[{“$month”:“$CreationDate”},9]},
{“$substr”:[{“$month”:“$CreationDate”},0,2]},
{“$concat”:[
"0",
{“$substr”:[{“$month”:“$CreationDate”},0,1]},
]},
]},
"-",
{“$cond”:[
{“$gt”:[{“$dayOfMonth”:“$CreationDate”},9]},
{“$substr”:[{“$dayOfMonth”:“$CreationDate”},0,2]},
{“$concat”:[
"0",
{“$substr”:[{“$dayOfMonth”:“$CreationDate”},0,1]},
]}
]}
]
},
{“cnt”:{“$sum”:1}
}}
{“$sort”:{“cnt”:-1}
]);
可能更好的方法是只使用date math,这将返回一个历元时间戳值,但在后期处理中很容易处理成date对象:
db.Document.aggregate([
{“$组”:{
“_id”:{
“$subtract”:[
{“$subtract”:[“$CreationDate”,新日期(“1970-01-01”)],
{“$mod”:[
{“$subtract”:[“$CreationDate”,新日期(“1970-01-01”)],
1000 * 60 * 60 * 24
]}
]
},
“cnt”:{“$sum”:1}
}},
{“$sort”:{“cnt”:-1}
])
尼尔的回答很中肯,但有一点缺陷。在条件中(检查月和日的数字是否需要加0)不是$gt
,而是$lte
使用$lte
,只有带有一位数字的月份和天数将以0开头
e、 g:2014-10-03,2014-08-03.将ISODate转换为各种日期格式的另一种更简单的方法是使用 将日期格式转换为“xxxx xx xx” 对于MONGO>=3.0(2015年之后) 如果一些可怜的人在2017年偶然发现这个问题,比如我: 从Mongo 3.0开始,现在有一个可用的操作员 这意味着如果您有合适的Date(),您应该能够简单地执行以下操作:
db.Document.aggregate(
, {$project: {_id:1, CreationDate:1}
, {$group: {
_id : { $dateToString: { format: "%Y-%m-$d", date: "$CreationDate" } },
cnt:{$sum:1}}}
, {$sort:{'cnt':-1}}
);
对于那些碰巧将日期存储在非日期字段中的人(多么高兴!),您可以在项目步骤中创建一个新的date()对象。
在我的例子中,日期存储为毫秒数(整数),我将毫秒数添加到0日期中
db.Document.aggregate(
, {$project: {
_id:1,
CreationDate: {"$add": [ new Date(0), "$CreatedOn" ]}
}
, {$group: {
_id : { $dateToString: { format: "%Y-%m-$d", date: "$CreationDate" } },
cnt:{$sum:1}}}
, {$sort:{'cnt':-1}}
);
是否有理由需要在MongoDB中完全格式化输出?我只需要编写一个小脚本,根据它接收到的文档格式化一些字符串输出。否则,你应该调查。菲利普,没有理由!我只是想探索一下。谢谢你,谢谢你。我认为这是2.6及更高版本中的一个新特性。我之前用的是2.4,实际上是3.0版的新版本。根据文档(答案中提供的链接)+1表示
$substr
。有点奇怪,$concat
需要一个字符串,而$substr
不需要。。。“强制转换”的有趣方式。在$cond语句中,“$gt”应该是“$lte”,这样,如果值小于或等于9,则真实值将进行计算,并导致“0”字符串的预填充。“{$cond:[,]}”这更适合作为尼尔答案的编辑甚至评论。。。(我猜你在这方面做得不够,对吧?)
db.Document.aggregate(
, {$project: {_id:1, CreationDate:1}
, {$group: {
_id : { $dateToString: { format: "%Y-%m-$d", date: "$CreationDate" } },
cnt:{$sum:1}}}
, {$sort:{'cnt':-1}}
);
db.Document.aggregate(
, {$project: {
_id:1,
CreationDate: {"$add": [ new Date(0), "$CreatedOn" ]}
}
, {$group: {
_id : { $dateToString: { format: "%Y-%m-$d", date: "$CreationDate" } },
cnt:{$sum:1}}}
, {$sort:{'cnt':-1}}
);