我在mongo中有一个多个日期的列表,我想找到每个日期之间的时间差(例如objectId 3和4之间的时间,objectId 4和5,objectId 5和6.我尝试了mongo&#39 ; s $减去,但它给出了我的答案,以毫秒为单位,转换时没有意义。另外,不应该是objectId 3的dateDiff值,因为它之前没有日期。< / p>
> db.collection.find({item:"1"})
{ "_id" : ObjectId("3"), "item" : "1", "date" : ISODate("2016-02-08T10:24:36Z") }
{ "_id" : ObjectId("4"), "item" : "1", "date" : ISODate("2016-02-13T10:24:36Z") }
{ "_id" : ObjectId("5"), "item" : "1", "date" : ISODate("2016-02-29T10:24:36Z") }
{ "_id" : ObjectId("6"), "item" : "1", "date" : ISODate("2016-03-13T10:24:36Z") }
> db.collection.aggregate([
{$match:{item:"1"}},
{$sort:{date:1}},
{$project:{dateDiff:{$subtract:[new Date(),"$date"]}}}
])
{ "_id" : ObjectId("3"), "dateDiff" : NumberLong("18412790289") }
{ "_id" : ObjectId("4"), "dateDiff" : NumberLong("17980790289") }
{ "_id" : ObjectId("5"), "dateDiff" : NumberLong("16598390289") }
{ "_id" : ObjectId("6"), "dateDiff" : NumberLong("15302390289") }
答案 0 :(得分:2)
您必须查看您尝试的语句,并了解您要求“数据库服务器”执行的操作是“从当前时间”中减去日期值,这是new Date()
实际正在做的事情。这解释了您从尝试中获得的输出,因为该值不是“之前的文档日期”。
如果你所追求的是前面每个项目和当前项目之间的日期差异,那么我真的不认为这是“数据库服务器”本身执行的任务。你要问的是,通过简单地处理光标并保持对前一个“日期”的引用然后简单地从当前减去它来更自然地解决这个问题:
var previousDate = false;
db.getCollection('collection').find().sort({ "item": 1, "date": 1 }).map( d => {
var diff = (previousDate) ? NumberLong(d.date - previousDate) : 0;
previousDate = d.date;
return Object.assign(d,{ diff })
})
返回:
{
"_id" : ObjectId("598b794c1b61b8b7a12329b4"),
"item" : "1",
"date" : ISODate("2016-02-08T10:24:36.000Z"),
"diff" : 0.0
},
{
"_id" : ObjectId("598b794c1b61b8b7a12329b5"),
"item" : "1",
"date" : ISODate("2016-02-13T10:24:36.000Z"),
"diff" : NumberLong(432000000)
},
{
"_id" : ObjectId("598b794c1b61b8b7a12329b6"),
"item" : "1",
"date" : ISODate("2016-02-29T10:24:36.000Z"),
"diff" : NumberLong(1382400000)
},
{
"_id" : ObjectId("598b794c1b61b8b7a12329b7"),
"item" : "1",
"date" : ISODate("2016-03-13T10:24:36.000Z"),
"diff" : NumberLong(1123200000)
}
这通常是最好的事情,因为自然事件是“一个接一个”,这就是光标实际处理的内容。 MongoDB本身没有“引用前一个文档的值”的真正方法,唯一的方法就是将值强制转换为“数组”进行处理。
因此,在大多数现实世界中,像“数组”这样的处理实际上并不实用,实际上通过将值存储在任何大小的数组中都会超过16MB BSON限制。
如果您认为必须“在服务器上”执行此操作,那么最有效的用法是应用$reduce
,在处理列表{{}}时可以访问“当前”和“之前已减少”的项目分别为{1}}和$$this
:
$$value
哪个输出
db.getCollection('collection').aggregate([
{ "$sort": { "item": 1, "date": 1 } },
{ "$group": {
"_id": "$item",
"diff": { "$push": "$date" }
}},
{ "$addFields": {
"diff": {
"$map": {
"input": {
"$reduce": {
"input": "$diff",
"initialValue": [],
"in": {
"$concatArrays": [
"$$value",
[{
"date": "$$this",
"diff": {
"$cond": {
"if": { "$eq": [{ "$size": "$$value" }, 0] },
"then": 0,
"else": {
"$subtract": ["$$this", { "$arrayElemAt": ["$$value.date", -1] }]
}
}
}
}]
]
}
}
},
"as": "d",
"in": "$$d.diff"
}
}
}},
{ "$unwind": "$diff" }
])
请注意,由于$reduce
喜欢它的其他语言对应物通常是“减少”结果,我们通过使用$concatArrays
“加入”“前一个”和“当前”来使返回的结果成为一个数组“输出。
每个项目的基本过程(除第一项的逻辑外)是使用索引{ "_id" : "1", "diff" : 0.0 }
{ "_id" : "1", "diff" : NumberLong(432000000) }
{ "_id" : "1", "diff" : NumberLong(1382400000) }
{ "_id" : "1", "diff" : NumberLong(1123200000) }
通过$subtract
$arrayElemAt
之前的结果,这意味着“最后”的项目数组,来自使用$group
通过之前的$push
阶段收集的“当前”项目。
由于需要“上一个日期”,$reduce
输出包含-1
值以确定每个值之间的差异。然后,包装$map
操作将提取实际的"date"
值,该操作仅返回该属性的值,并返回到最终结果,然后按顺序处理数组$unwind
将这些项目放回文件表格。
较少的管道阶段总是意味着更好的性能,因为每个阶段本质上都是“通过数据”并且需要时间。所以这里$group
做“集合”,下一个阶段找到“差异”。这基本上就是操作,它只需要这两个阶段。
这有点“玩杂耍”,但比你可能做的要少得多,并且是实际解决“在服务器上”的最高效的方式。但这确实不是一个“服务器”问题,并且更适合简单地“按顺序处理光标”,就像最初显示的那样。
答案 1 :(得分:1)
使用新的var tween = KUTE.fromTo('#original', {path: '#original' }, { path: '#swimming' }, {morphPrecision:64, morphIndex:32, repeat:161803}).start();
,您有效地将当前日期与相应日期字段中的日期进行比较。你想要做的是将不同文档中的值相互比较,这可以通过创建一些包含所有日期的辅助数组来实现。
这是一个有效的评论版本:
Date()