猿问

MongoDB - 重建文档,保留数组的最后一个元素

示例文档https://pastebin.com/x2kVUnP3

理解数据

每个字段数组计数与 fetch_dates 相同,因此如果我们想获取2019-06-07 05:34:29的数据集,它将返回所有内部字段$arrayElemAt = 1以获得最新结果,对于对应的字段。

期望的结果

主要思想是重建所有文档并仅保留每个字段的最新 fetch_date 和最后一个值。在这种情况下,只需保留图像的橙色线即可。

问题

基本上我不知道从哪里开始或如何开始,如果可以的话。每个文档可以有不同的数组大小 (fetch_dates) 但结构是相同的。有 225k 个文档要处理,平均大小为 2.5kb。任何提示将不胜感激。

我的初步想法

我想通过 PHP 脚本获取所有字段及其最后一个元素,例如首先遍历所有文档,然后遍历所有字段和 $project 值,我认为这是一个$arrayElemAt => [ $field3.field3_1, -1 ]坏主意。

我正在使用 PHP - Laravel,但我能够转换查询以使其在那里工作。


ITMISS
浏览 120回答 1
1回答

小怪兽爱吃肉

这是一个纯粹来自 MongoDB shell 的解决方案。我的解决方案依赖于聚合管道和使用项目操作。在你的问题中你说,每个文档可以有不同的数组大小 (fetch_dates) 但结构是相同的。基于此,我认为没有理由必须遍历数据库中的所有文档。相反,您可以只从数据库中提取一个文档并使用它来提出一个应该适用于数据库中所有文档的投影。这是我想出的代码。function buildProjection(doc, prepend) {  var projection = {};  Object.keys(doc)    .forEach(key => {      var val = doc[key];      var path = prepend==null? key : prepend + '.' + key;      if (key == '_id') {        projection[key] = 1;      } else if ( Array.isArray(val) ) {        projection[key] = { '$slice' : [ '$'+path, -1 ] };      } else if ( typeof val === 'object' && val !== null ) {        projection[key] = buildProjection(val, path);      } else {        projection[key] = 1;      }    });    return projection;}/* * Pull a document out of the database and build the projection based off of it. * You may want to specify a particular document in the findone * that you know to be structured correctly*/var sample = db.myCollection.findOne({});var projection = buildProjection(sample, null);db.myCollection.aggregate([  // apply the build projection  { $project: projection },  // insert results into another collection  { $out: 'rebuiltWithLatest' }]);我不确定您是否想将结果保存在另一个集合中。我用这个解决方案这样做了。花了几秒钟,但我用 300k 文档运行这个没有问题,这很像你的链接示例。如果您只想查看文档,请从聚合管道中删除 $output 操作。然后它将返回一个游标对象,您可以迭代该对象以查看其他结果。
随时随地看视频慕课网APP
我要回答