2016-02-20 52 views
2

我试图找到使用id字段在我的分片收集的重复,这是这种模式的失败 -的MongoDB - 骨料与内存错误

"id" : { 
     "idInner" : { 
      "k1" : "v1", 
      "k2" : "v2", 
      "k3" : "v3", 
      "k4" : "v4" 
     } 
} 

我用下面的查询,但收到了“异常:超出了$ group的内存限制,但不允许外部排序。通过allowDiskUse:true来选择加入。“错误,即使我在查询中使用了“allowDiskUse:true”。

db.collection.aggregate([ 
    { $group: { 
    _id: { id: "$id" }, 
    uniqueIds: { $addToSet: "$_id" }, 
    count: { $sum: 1 } 
    } }, 
    { $match: { 
    count: { $gte: 2 } 
    } }, 
    { $sort : { count : -1} }, 
    { $limit : 10 } 
], 
{ 
    allowDiskUse : true 
}); 

是否有另一种方法来得到我想要的,或者我应该通过上述查询的其他方法?谢谢。

+0

'_id'字段本身始终索引一个“唯一”约束。它**不能**包含重复项。 –

+0

这不是“_id”字段,在我的情况下,我让mongo默认填充。我有我自己的“id”(没有下划线),它包含我的密钥。 – user3723491

+0

你真的需要在你的组中使用'uniqueIds:{$ addToSet:“$ _id”}'吗?这可能会缓解一些内存问题。 – ThrowsException

回答

2

请在运行命令中使用allowDiskTrue。

db.runCommand(
    { aggregate: "collection", 
    pipeline: [ 
    { $group: { 
    _id: { id: "$id" }, 
    uniqueIds: { $addToSet: "$_id" }, 
    count: { $sum: 1 } 
    } }, 
    { $match: { 
    count: { $gte: 2 } 
    } }, 
    { $sort : { count : -1} }, 
    { $limit : 10 } 
], 
    allowDiskUse: true 
    } 
) 

让我知道这是否适合你。

+0

对不起,我只是试了一下,效果很好。谢谢。 – user3723491

2

首先运行一个$match,以便只保留位于某个范围之间的文档,例如id.idiInner.k1,以便您仅针对该范围获取结果。由于您对id键有重复感兴趣,所有重复的文档都将满足此条件。看看你应该缩小这个范围,然后在下一个范围内运行它,直到你覆盖所有文档。

如果是必须经常做的事情,自动化,通过声明范围,将它们放入一个循环中,保留每次运行的副本并将结果合并到最后。

另一个快速黑客/特技将绕过mongos并直接在每个碎片运行聚集。这样做会将您的文档大致限制为(假设分布良好的分片)到docs/number_of_shards,并且您可能会克服内存限制。在第二种方法中,我假设你的分片键是id键,但是如果不是这样,那么这种方法将不起作用,因为相同的重复文档将散布在分片中。

+0

感谢您使用$ match来缩小结果。这帮助我得到我想要的。 – user3723491