mongo:有效保留最近的N个重复记录

时间:2012-04-02 15:45:33

标签: mongodb mapreduce

假设:

  • mongo集合中有数百万条记录。
  • 每个记录有10个字段,其中4个是复合非唯一索引,我们称之为KEY。
  • 每条记录都有一个时间戳。
  • 有些记录具有相同的KEY值。
  • 可能在数千条记录中找到相同的KEY。

我想创建另一个集合,其中包含原始集合的一个子集,我希望将每个KEY的重复数量限制为不超过某个常量,例如1000,其中只有最新的重复项必须是包括在内。

因此,如果有10000条记录具有相同的KEY,那么新集合中将只有最近的1000条记录。

下面是我创建聚合集合的代码,其中包含按KEY分组的所有原始记录。所以,我错过了仅保留最近的1000的部分,但我的代码已经非常低效,所以我认为我做错了:

from pymongo import Connection

def main():
  with Connection() as connection:
    mydb = connection.mydb
    try:
      mydb.aggregated.drop()
      mydb.static.map_reduce("""
// map
function() {
  emit({
    indexed_field1: this.indexed_field1,
    indexed_field2: this.indexed_field2,
    indexed_field3: this.indexed_field3
  }, {
    id: this._id,
    ts: this.ts,
    // other fields
  });
}
""", """
// reduce - group the records with the same KEY
// return the given values array wrapped in an object
function(key, values) {
  for (var i = 0; i < values.length; ++i) {
    if (values[i].items) {
      values[i] = values[i].items;
    }
  }
  return {items: values};
}
""", 'aggregated', finalize="""
// finalize by flattening the value, which is likely to be an array of nested arrays
function(key, value) {
  function flatten(value, collector) {
    var items = value;
    if (!(value instanceof Array)) {
      if (!value.items) {
        collector.push(value);
        return;
      }

      items = value.items;
    }
    for (var i = 0; i < items.length; ++i) {
      flatten(items[i], collector);
    }
  }

  var collector = [];
  flatten(value, collector);
  return collector;
}
""")
    except Exception as exc:
      print exc

if __name__ == "__main__":
  main()

另一个问题是我违反了减少应该返回与地图相同类型的主体,但我认为在我的情况下它是可以的,因为我减少并最终处理它。

感觉我走错了路。建议?

修改

数据如下所示:

{_id: , key1: , key2: , key3: , ts: , bla-bla-bla}

例如:

  • 包含(key1,key2,key3) == ('yaba', 'daba', 'doo')
  • 的20,000条记录
  • 带有(key1,key2,key3) == ('yogi', 'bear', '')
  • 的15,000条记录
  • 包含(key1,key2,key3) == ('yo', 'ho', 'ho')
  • 的700条记录

在流程结束时,我需要留下:

  • 最近的1000条yaba-daba-doo记录
  • 1,000份最近的瑜伽熊记录
  • 所有yo-ho-ho记录(因为它们少于1000个)

1 个答案:

答案 0 :(得分:0)

我有一种不好的感觉我错过了一些非常重要的东西,在我决定尝试编程之前应该清醒过来: -

好的,因为你有一个可能看起来像的文件:

{
  _id: {},
  key1: '', key2: '', key3: '', key4: '', key5: '', key6: '', key7: '', key8: '', key9: '', key10: ''
}

您想要使用[key2,key3,key5,key7]的复合键,然后使用这个确切的键拉出最新的1000个重复文档。

不能通过一点点黑客来解决这个问题吗?我的意思是你基本上得到了最新的一把钥匙?

db.awesome_collection.find({ 'key2': '', 'key3': '', 'key5': '', 'key7': '' }).sort({ 'ts': -1 }).limit(1000);

这不是吗?

我的意思是非常聪明,你实际上可以创建一个脚本,它可以比MR运行得更快,通过原始表格根据这些查询重新计算。