由于我经常遇到 mongodb 的文档大小限制以及聚合框架的组限制 >16M,这取决于我需要处理的数据量,所以我寻找一个简单的解决方法。
该解决方案还必须适用于单个节点(并且不得需要多个 mongos)。
简而言之,这是一个用于查找的聚合
(a) 一个字段中唯一值的数量(计数),并将该数量按另一个字段分组
(b) 唯一 ID 出现的频率或计数。
一个例子可以使任务更容易理解:假设有一个包含 2 个字段的集合,即姓氏和姓氏。
(例 a)每个姓氏有多少个不同的姓氏?结果可能是:姓氏“smith”有 1000 个唯一(不同)的姓氏,姓氏“schulz”的人有 500 个不同的姓氏等。
=> 这也可以通过不同的计数和/或 mapreduce 等来解决。没有超过限制。无论如何,这似乎是一个缓慢的表扫描,聚合框架可以更快地完成任务。
(例如 b)每个姓氏的姓氏有多受欢迎?结果:对于姓氏“smith”,有 500 个只出现一次的姓氏,200 个出现 2 次的姓氏,45 个出现了 3 次我们的数据,...
=> 在这里使用 mongodb 的聚合框架非常舒服,它可以快速正确地处理这个任务。然而,在 15GB 的集合中尝试具有大量唯一值的任务时,它担心 16M 的限制。
第一个解决方法是成功的,但只是一个快速的'n'dirt 不可扩展的技巧:我没有处理所有数据和之后的 $group,而是为每个 $group-item 过滤($match)。使用上面的示例,我查找所有不同的姓氏,对每个姓氏运行一次聚合,并在聚合开始之前减少管道数据。
如果单个 $group-item(姓氏)的数据量不是太多,这可以避免 16M 限制问题。=> 只有 quick'n'dirty 解决方法。
另一个想法是 COUNT 的帮助集合。
我可以迭代每个输入文档并使用计数器将姓氏和每个姓氏的一个字段写入另一个集合。
例如 surname=John count_with_Lastname.smith=10, count_with_Lastname.brown=2, ...
构建这个助手集合非常慢,不是吗?当递增 +1 时,即每个输入文档 1 次更新/写入,我担心这可能会永远持续下去:-(
是否有解决此任务的最佳实践或技巧(没有多个节点且没有 Hadoop 或替代方案)?
请告诉我
一旦你超出了你提到的限制(直到至少支持 $out ),那么你最好的选择是 Map Reduce。如果您要运行多个 Map Reduce 作业,我建议至少使用 2.4 版(使用 V8 引擎,多线程)。有关如何使用 Map Reduce 进行唯一计数的示例,请查看此处:
http://cookbook.mongodb.org/patterns/unique_items_map_reduce/