如何使用javascript获取mongoDB中相邻记录之间的差异?例如,如果我在集合中有以下三个文档:
{
"_id" : ObjectId("50ed90a55502684f440001ac"),
"time" : ISODate("2013-02-13T15:45:41.148Z")
}
{
"_id" : ObjectId("50ed90a55502684f440001ac"),
"time" : ISODate("2013-02-13T15:45:42.148Z")
}
{
"_id" : ObjectId("50ed90a55502684f440001ac"),
"time" : ISODate("2013-02-13T15:45:45.148Z")
}
我想在相邻值之间的“时间”字段中获取差异:
{
"_id" : ObjectId("50ed90a55502684f440001ac"),
"time" : ISODate("2013-02-13T15:45:41.148Z"),
"time_difference" : null
}
{
"_id" : ObjectId("50ed90a55502684f440001ac"),
"time" : ISODate("2013-02-13T15:45:42.148Z"),
"time_difference" : 1
}
{
"_id" : ObjectId("50ed90a55502684f440001ac"),
"time" : ISODate("2013-02-13T15:45:45.148Z"),
"time_difference" : 3
}
有关如何在javascript / mongoDB中高效执行此操作的任何想法?感谢。
答案 0 :(得分:2)
您需要确保的一件事是您对要用于装饰记录的查询进行排序。如果没有使用排序,它实际上将使用查找顺序,而不是$natural
顺序。
查询顺序可能因查询而异,因此如果您在2分钟内运行查询两次,您可能会发现它们不会返回相同的顺序。但是,您的查询似乎会在tiem_difference
上进行逻辑排序。
还应注意,通过正常查询无法做到这一点。我也没有通过聚合框架看到一种简单的方法。
所以看来下一个合理的方法似乎是使用多个查询或客户端处理。使用类似上面@Marlon定义的函数,客户端处理可能更好。
答案 1 :(得分:1)
有一件事,我想清楚你。与MYSQL不同,MongoDB不会保证这个职位。我的意思是,MongoDB会在不同的时间给你不同的排序。因此在每次阅读时比较相邻文件可能会给出不同的结果。
如果您对此感到满意,并且想要进行比较,请尝试使用MongoDB的MapReduce http://docs.mongodb.org/manual/applications/map-reduce/
答案 2 :(得分:1)
假设这3个对象在数组中出现,您可以执行以下操作:
var prevTime;
var currentTime;
for(var i = 0; i < records.length; i++)
{
currentTime = new Date(records[i].time).getTime();
records[i].time_difference = currentTime - prevTime;
prevTime = currentTime;
}
当然,您需要将位交换出来以使其使用来自mongo的记录。
如果您需要进行更复杂的日期计算,我强烈建议您查看datejs(如果需要,可以获取节点包装器。)
答案 3 :(得分:1)
我不知道七年前提出这个问题时是否如此,但这可以在聚合框架中完全解决。假设集合名称为AdjacentDocument
,则以下汇总将获得您想要的结果:
db.AdjacentDocument.aggregate(
{$sort: {time: 1}},
{$group: {_id: 0, document: {$push: '$$ROOT'}}},
{$project: {documentAndPrevTime: {$zip: {inputs: ['$document', {$concatArrays: [[null], '$document.time']}]}}}},
{$unwind: {path: '$documentAndPrevTime'}},
{$replaceWith: {$mergeObjects: [{$arrayElemAt: ['$documentAndPrevTime', 0]}, {prevTime: {$arrayElemAt: ['$documentAndPrevTime', 1]}}]}},
{$set: {time_difference: {$trunc: [{$divide: [{$subtract: ['$time', '$prevTime']}, 1000]}]}}},
{$unset: 'prevTime'}
);
首先,将文档从最旧到最新进行排序。它们被分组为一个文档,文档存储在有序数组字段中:
{$sort: {time: 1}},
{$group: {_id: 0, document: {$push: '$$ROOT'}}}
/*
{
"_id" : 0,
"document" : [
{
"_id" : ObjectId("50ed90a55502684f440001ac"),
"time" : ISODate("2013-02-13T15:45:41.148Z")
},
{
"_id" : ObjectId("50ed90a55502684f440001ad"),
"time" : ISODate("2013-02-13T15:45:42.148Z")
},
{
"_id" : ObjectId("50ed90a55502684f440001ae"),
"time" : ISODate("2013-02-13T15:45:45.148Z")
}
]
}
*/
接下来,将以前的时间压缩到文档数组中,创建一个[document, previousTime]
数组:
{$project: {documentAndPrevTime: {$zip: {inputs: ['$document', {$concatArrays: [[null], '$document.time']}]}}}}
/*
{
"_id" : 0,
"documentAndPrevTime" : [
[
{
"_id" : ObjectId("50ed90a55502684f440001ac"),
"time" : ISODate("2013-02-13T15:45:41.148Z")
},
null
],
[
{
"_id" : ObjectId("50ed90a55502684f440001ad"),
"time" : ISODate("2013-02-13T15:45:42.148Z")
},
ISODate("2013-02-13T15:45:41.148Z")
],
[
{
"_id" : ObjectId("50ed90a55502684f440001ae"),
"time" : ISODate("2013-02-13T15:45:45.148Z")
},
ISODate("2013-02-13T15:45:42.148Z")
]
]
}
*/
接下来,解开文档和时间数组,为每个初始文档创建一个文档:
{$unwind: {path: '$document', includeArrayIndex: 'arrayIndex'}}
/*
{
"_id" : 0,
"documentAndPrevTime" : [
{
"_id" : ObjectId("50ed90a55502684f440001ac"),
"time" : ISODate("2013-02-13T15:45:41.148Z")
},
null
]
}
{
"_id" : 0,
"documentAndPrevTime" : [
{
"_id" : ObjectId("50ed90a55502684f440001ad"),
"time" : ISODate("2013-02-13T15:45:42.148Z")
},
ISODate("2013-02-13T15:45:41.148Z")
]
}
{
"_id" : 0,
"documentAndPrevTime" : [
{
"_id" : ObjectId("50ed90a55502684f440001ae"),
"time" : ISODate("2013-02-13T15:45:45.148Z")
},
ISODate("2013-02-13T15:45:42.148Z")
]
}
*/
接下来,我们用文档数组元素的值替换文档,并与先前的时间元素合并(如果它是初始索引,则使用null):
{$replaceWith: {$mergeObjects: [{$arrayElemAt: ['$documentAndPrevTime', 0]}, {prevTime: {$arrayElemAt: ['$documentAndPrevTime', 1]}}]}}
/*
{
"_id" : ObjectId("50ed90a55502684f440001ac"),
"time" : ISODate("2013-02-13T15:45:41.148Z"),
"prevTime" : null
}
{
"_id" : ObjectId("50ed90a55502684f440001ad"),
"time" : ISODate("2013-02-13T15:45:42.148Z"),
"prevTime" : ISODate("2013-02-13T15:45:41.148Z")
}
{
"_id" : ObjectId("50ed90a55502684f440001ae"),
"time" : ISODate("2013-02-13T15:45:45.148Z"),
"prevTime" : ISODate("2013-02-13T15:45:42.148Z")
}
*/
最后,我们通过将time_difference
设置为两个时间字段的差值并删除临时prevTime
字段来更新文档。由于两个日期之间的时差以毫秒为单位,并且您的示例使用秒,因此我们通过除以1000并截断来计算秒。
{$set: {time_difference: {$trunc: [{$divide: [{$subtract: ['$time', '$prevTime']}, 1000]}]}}},
{$unset: 'prevTime'}
/*
{
"_id" : ObjectId("50ed90a55502684f440001ac"),
"time" : ISODate("2013-02-13T15:45:41.148Z"),
"time_difference" : null
}
{
"_id" : ObjectId("50ed90a55502684f440001ad"),
"time" : ISODate("2013-02-13T15:45:42.148Z"),
"time_difference" : 1
}
{
"_id" : ObjectId("50ed90a55502684f440001ae"),
"time" : ISODate("2013-02-13T15:45:45.148Z"),
"time_difference" : 3
}
*/