从一个大的MongoDB集合中使用PHP选择每个第N个元素?

10

我有一个包含大约4百万元素的MongoDB集合。

我想从整个集合中均匀地获取X个元素。

例如,从集合中获取1000个元素-每4000行一个元素。

目前,我正在使用光标获取整个集合,然后仅编写每N个元素。这可以给我所需的内容,但是加载巨大的集合的原始时间很长。

有没有简单的方法来做到这一点?目前,我的猜测是在递增的索引属性上进行JS查询,使用模数。此PHP实现:

db.collection.find({i:{$mod:[10000,0]}})

但这似乎会花费与运行查询一样多的时间。

Jer


1
你找到任何解决方案了吗? - coding_idiot
6个回答

1

使用$sample

这将返回一个随机样本,大致是“每N个文档”。

要在结果集中确切地接收每个第N个文档,您必须提供排序顺序并迭代整个结果集,在应用程序中丢弃所有不需要的文档。


0

我认为主要问题在于集合可以分布在多台服务器上,因此您必须遍历整个集合。


在这种情况下,我正在本地服务器上运行整个程序。 - blprnt

0

不要将整个数据集放入游标中。由于行顺序不重要,只需从总数中收集x个随机行,将其作为结果返回,然后修改这些记录。


问题在于我需要从我的集合中均匀分布的元素 - 即每1000个元素。 - blprnt
创建一个计数字段,然后使用Map过滤每个第n个元素,最后使用Reduce操作该记录。 - Ric Johnson
谢谢...我会尝试一下。我已经有一个计数字段了。只需要尝试理解一下Map Reduce文档。 - blprnt
有进展了吗?如果我的回答对您有帮助,请投票支持并发布您的解决方案,以便其他人也能学习! - Ric Johnson

0
个人而言,我会在设计中加入“模数”值,并使用代表数据的函数进行填充 - 因此,如果您的数据是在一天中定期插入的,则可以对时间进行模数运算;如果没有可预测性,则可以使用随机值。由于集合规模较大,因此很快就会趋向于均匀分布。
以下是一个使用随机值的示例...
    // add the index
    db.example.ensureIndex({modulus: 1});
    // insert a load of data
    db.example.insert({ your: 'data', modulus: Math.round((Math.random() * 1000) % 1000) });
    // Get a 1/1000 of the set
    db.example.find({modulus: 1});
    // Get 1/3 of the set
    db.example.find({modulus: { $gt: 0, $lt: 333 }});

0
一个简单(但效率较低)的处理方式是使用流(stream)。
var stream = collection.find({}).stream();
var counter = 0;

stream.on("data", function (document) {
  counter++;

  if (counter % 10000 == 0) {
    console.log(JSON.stringify(document, null, 2));
    //do something every 10,000th time
  }
});

-7
如果您的数据存储在 SQL 数据库中,就像应该的那样,... 这个问题就不会出现在 PHP 中,答案也会变得如此简单和快速...
将任何东西加载到游标中,而不是直接在数据库中计算信息,绝对是一个坏主意,难道不能直接在 MongoDB 中完成这个操作吗?

这个答案太反向了。 - jtromans
当处理仅有4M个元素并且执行非MongoDB本地操作时,您应该使用PostgreSQL。 - Morg.
为什么?为什么在这里使用PostgreSQL会更好?我是SQL数据库的重度用户,但这种查询对大多数数据库来说都不是一个好选择。此外,“MongoDB东西”?看起来你并不真正了解MongoDB,无法在这里发表权威意见。甚至不确定你在回答的第二部分所指的是什么。 - Sammaye
这个查询在任何好的关系型数据库管理系统(pgsql、oracle、mssql)中都是完全正常的。 - Morg.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接