Python 在MongoDB中,如何找到大型切分集合的不同值?

Python 在MongoDB中,如何找到大型切分集合的不同值?,python,mongodb-query,Python,Mongodb Query,我有一个大型mongodb收藏: 有3个碎片 总计3亿条记录(至少) 切分键为(字段1:1,字段2:1) 还有其他非索引字段 Field1是一个约200个字符的字符串 字段2是一个int Field1大约有1000万个不同的值,并且一直在添加更多的值 第1部分:不同的值 我需要找到field1的所有不同值 调用db.myCollection.distinct(“field1”)失败,因为结果集中的数据超过16MB 因为shard键是一个索引,所以这应该是一个覆盖查询 第2部分:返回排序结果

我有一个大型mongodb收藏:

  • 有3个碎片
  • 总计3亿条记录(至少)
  • 切分键为(字段1:1,字段2:1)
  • 还有其他非索引字段
  • Field1是一个约200个字符的字符串
  • 字段2是一个int
  • Field1大约有1000万个不同的值,并且一直在添加更多的值
第1部分:不同的值

我需要找到field1的所有不同值

调用db.myCollection.distinct(“field1”)失败,因为结果集中的数据超过16MB

因为shard键是一个索引,所以这应该是一个覆盖查询

第2部分:返回排序结果

假设上面有一个答案,我想让它从失败中恢复,也就是说,按排序顺序返回结果。这并不重要

排序输出的目标是:如果查询中途失败,我可以通过添加field1:{$gt:lastGoodValue}的查询说明符从中断处继续


那么:这可能吗?容易的?我必须聚合还是映射减少?目前,我正在迭代所有300M记录,它会不必要地推送大量数据。

集合distinct命令()返回单个变量,即数组。此变量作为BSON文档发送,在MongoDB中具有16MB的最大大小限制

在某些情况下,将结果集放在一个数组中是很方便的,但是如果不能确定它是否适合16MB,那么您将无法使用它,正如您所发现的那样

第一部分答案 相反,您可以在聚合命令中使用$group阶段。您也可以使用MapReduce,但聚合具有更好的性能,因此我将重点介绍这一点

db.myCollectoin.aggregate( [ { $group : { _id : "$myField" } } ] )
这将把结果从单个数组变量更改为游标,与普通的查询/查找命令相同。因此,您在客户端迭代不同值的方式将有所不同,但您可以继续获取越来越多的值,直到光标完成

无论您是拥有群集、副本集还是独立mongod,都可以使用相同的命令。一个重要的性能考虑因素是是否对被明确分组的字段进行了索引,但正如您提到的,该字段是切分键中的前导字段,我们知道它是

第二部分答案 是的,你可以分类。在$group后面添加$sort阶段

db.myCollection.aggregate( [ 
  { $group : { _id : "$myField" } }, 
  { $sort: { "_id": 1 } } 
] )
如果必须从某个点重新启动查询,则需要在聚合管道中添加一个作为第一个操作。例如,
{$match:{“myField”:{“$gt”:“AbCdEf….”}},

聚合新用户注意事项:上面$sort阶段的第二个“\u id”是$group阶段输出的“\u id”字段,即不同的“myField”值。它不是根据基础集合中的“\u id”值进行排序

如果愿意,可以使用$project阶段重命名中间阶段的“\u id”键名

db.myCollection.aggregate( [ 
  { $group : { _id : "$myField" } }, 
  { $project : { 
     "_id" : false, /*stop it appearing as "_id" */
     "myField" : "$_id" /*put original field name "myField" back on*/
  } }, 
  { $sort: { "myField": 1 } } 
] )

集合distinct命令()返回单个变量,即数组。此变量作为BSON文档发送,在MongoDB中具有16MB的最大大小限制

在某些情况下,将结果集放在一个数组中是很方便的,但是如果不能确定它是否适合16MB,那么您将无法使用它,正如您所发现的那样

第一部分答案 相反,您可以在聚合命令中使用$group阶段。您也可以使用MapReduce,但聚合具有更好的性能,因此我将重点介绍这一点

db.myCollectoin.aggregate( [ { $group : { _id : "$myField" } } ] )
这将把结果从单个数组变量更改为游标,与普通的查询/查找命令相同。因此,您在客户端迭代不同值的方式将有所不同,但您可以继续获取越来越多的值,直到光标完成

无论您是拥有群集、副本集还是独立mongod,都可以使用相同的命令。一个重要的性能考虑因素是是否对被明确分组的字段进行了索引,但正如您提到的,该字段是切分键中的前导字段,我们知道它是

第二部分答案 是的,你可以分类。在$group后面添加$sort阶段

db.myCollection.aggregate( [ 
  { $group : { _id : "$myField" } }, 
  { $sort: { "_id": 1 } } 
] )
如果必须从某个点重新启动查询,则需要在聚合管道中添加一个作为第一个操作。例如,
{$match:{“myField”:{“$gt”:“AbCdEf….”}},

聚合新用户注意事项:上面$sort阶段的第二个“\u id”是$group阶段输出的“\u id”字段,即不同的“myField”值。它不是根据基础集合中的“\u id”值进行排序

如果愿意,可以使用$project阶段重命名中间阶段的“\u id”键名

db.myCollection.aggregate( [ 
  { $group : { _id : "$myField" } }, 
  { $project : { 
     "_id" : false, /*stop it appearing as "_id" */
     "myField" : "$_id" /*put original field name "myField" back on*/
  } }, 
  { $sort: { "myField": 1 } } 
] )

非常感谢。我查阅了所有MongoDB文档,但没有详细说明。我建议有人把一个“常见的查询”放在一起,因为它必须放在上面,我已经花了很长时间收集了好几本书,最后才抽出时间在这里询问。伟大的非常感谢。我查阅了所有MongoDB文档,但没有详细说明。我建议有人把一个“常见的查询”放在一起,因为它必须放在上面,我已经花了很长时间收集了好几本书,最后才抽出时间在这里询问。伟大的