我有一个大型的mongodb系列:
第1部分:DISTINCT VALUES
我需要找到field1的所有不同值。
调用db.myCollection.distinct(" field1")失败,因为结果集中的数据超过16MB。
由于分片键是索引,因此应该是一个覆盖查询。
第2部分:返回已分类的结果
假设有上述答案,我希望从故障中恢复,即按排序顺序返回结果。这不重要。
排序输出的目标:如果查询中途失败,我可以通过添加field1:{$ gt:lastGoodValue}的查询说明符从我停止的地方继续。
所以:这可能吗?简单?我必须聚合或map-reduce吗?目前,我正在迭代所有300M记录,并且不必要地推送了大量数据。
答案 0 :(得分:1)
集合distinct命令(doc link)返回单个变量,即数组。此变量作为BSON文档发送,在MongoDB中具有16MB的最大大小限制。
将结果集放在数组中对于某些情况很方便,但如果它不能确保适合16MB那么你将无法使用它,正如你所发现的那样。
相反,您可以retrieve distinct values在聚合命令中使用$ group阶段。您也可以使用MapReduce,但聚合具有更好的性能,因此我将重点关注它。
db.myCollectoin.aggregate( [ { $group : { _id : "$myField" } } ] )
这会将单个数组变量的结果更改为游标,与普通查询/查找命令相同。因此,您在客户端迭代不同值的方式会有所不同,但您可以继续获取越来越多的值,直到光标结束。
使用相同的命令,无论您是拥有群集,副本集还是独立的mongod。一个重要的性能考虑因素是明确分组的字段是否已编入索引,但正如您所提到的,该字段是分片键中的前导字段,我们知道它是。
是的,你可以对它进行排序。在$ group之后添加$ sort阶段。
db.myCollection.aggregate( [
{ $group : { _id : "$myField" } },
{ $sort: { "_id": 1 } }
] )
如果必须从某一点再次重新启动查询,则应添加$match stage作为聚合管道中的第一个操作。例如。 { $match: {"myField": { "$gt": "AbCdEf...."} } },
请注意新的聚合用户 :$ sort阶段中的第二个“_id”是$ group阶段输出的“_id”字段,即不同的“myField”值。它不是基础集合中“_id”值的排序。
如果您愿意,可以使用$ project阶段重命名该中间阶段的“_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 } }
] )