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

问题描述 投票:0回答:1

文件示例 https:/pastebin.comx2kVUnP3

了解数据

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

Data relation

希望的结果

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

问题

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

我最初的想法是

我想通过一个PHP脚本得到所有的字段和它的最后一个元素,就像先迭代所有的文档,然后再迭代所有的字段和$project值。$arrayElemAt => [ $field3.field3_1, -1 ] 我想这是一个坏主意。

我使用的是PHP - Laravel,但我能够转换查询,让它在那里工作。

php laravel mongodb
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' }
]);

我不确定你是否想把结果保存在另一个集合中。我用这个解决方案做了。它花了几秒钟,但我在运行这个30万个文档时没有任何问题,这些文档很像你的链接示例。

如果你只想查看文档,从聚合管道中删除$output操作。然后它将返回一个游标对象,你可以迭代查看其他结果。

© www.soinside.com 2019 - 2024. All rights reserved.