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

时间:2011-06-12 17:20:57

标签: php mongodb

我有一个包含~4M元素的MongoDB集合。

我想抓住那些元素的X个数,在整个集合中均匀分布。

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

现在,我将整个集合放在游标中,然后只编写每个第N个元素。这给了我我需要的东西,但巨大的收藏品的原始负载需要很长时间。

有一种简单的方法吗?现在我猜测的方法是在增量索引属性上使用模数进行JS查询。这个的PHP实现:

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

但这似乎可能需要花费同样多的时间来运行查询。

7 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

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

答案 2 :(得分: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 }});

答案 3 :(得分:0)

这不是Map Reduce Job的完美用例吗?

答案 4 :(得分:0)

一种简单(低效)的方法是使用流。

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
  }
});

答案 5 :(得分:0)

使用$sample

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

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

答案 6 :(得分:-4)

如果只有你的数据存在于sql数据库中,那么......这个问题不会出现在PHP中,答案会如此简单快捷......

将任何内容加载到游标中而不是直接在db中计算信息肯定是一个坏主意,是不是可以在MongoDB中直接执行此操作?