mongodb E11000 duplicate key error的几个可能的原因

assert: command failed: {
	"ok" : 0,
	"errmsg" : "insert for $out failed: { connectionId: 65, err: \"E11000 duplicate key error collection: admin.tmp.agg_out.6 index: _id_ dup key: { : 1 }\", code: 11000, codeName: \"DuplicateKey\", n: 0, ok: 1.0 }",
	"code" : 16996,
	"codeName" : "Location16996"
} : aggregate failed

最近在做聚合(aggreate)处理时总是报以上的错误,现在分析可能导致其发生几个原因
1. 数据库中存在重复数据
当存在重复数据时,我们需要对重复的数据保留一条外删除其余的重复文档数据(document),我们可以根据数据量的大小来使用不同的方法对重复数据进行删除
1.1 当数据量较小时(具体不好把握,大约几万几十万条吧),我们可以这样处理(以下dbname为表名,fieldname为字段名):

var duplicates = [];

db.dbname.aggregate([
  { $group: { 
    _id: { fieldname: "$fieldname"}, // 根据一个或多个字段进行分组,字段相同的document为一组
    dups: { "$addToSet": "$_id" }, //将字段相同的document的_id放在一个列表中
    count: { "$sum": 1 }  //统计相同document的个数
  }}, 
  { $match: { 
    count: { "$gt": 1 }    // 匹配大于1条的document
  }}
])               
.forEach(function(doc) {
    doc.dups.shift();      // 对于重复的document,保留第一条,剩下的的删除
    doc.dups.forEach( function(dupId){ 
        duplicates.push(dupId);   // 获取要删除的_id字段
        }
    )    
})

// 如果你想查看删除的重复的document的_id字段,你可以使用下面这句话
printjson(duplicates);     

// 一次删除重复的数据  
db.dbname.remove({_id:{$in:duplicates}})

以上详细可以查看:
https://stackoverflow.com/questions/13190370/how-to-remove-duplicates-based-on-a-key-in-mongodb/13190994

1.2 当数据量很大时(几千万到几亿数据量),我们可以这样处理:

1.2.1 将数据以json格式导出(假设表名为data)

mongoexport  -d 数据库名 -c data   -o D:\data.json

1.2.2 删除data表

db.data.remove({}) 
或者
使用robomongo客户端的话可以直接右键+drop collection

1.2.3 重新建一个名为data的表并建立唯一索引
注意:在data中我们可以找一下哪一个字段必须是唯一的,比如我有一个关于论文信息的表,那它的doi就一定是唯一的,只要doi重复就说明两条数据一定是重复的,就必须删除那些重复的

db.data.ensureIndex({dbfield: 1},{unique: 1})//dbfield指的是那个唯一的字段

1.2.4 将json数据导入data中

mongoimport -d 数据库名 -c 数据表  --type json --file D:\data.json

在导入的过程中,我们发现重复记录被删除,这种方法速度虽然不大快,但确实真的好用,推荐!!!

2. 使用聚合(aggreate)时应该注意的导致数据重复的原因

db.all.aggregate([
{$lookup: {
    from: 'data',
    localField: 'doi',
    foreignField: 'cited',
   as: 'data_docs'}
    },
    {$unwind: '$data_docs'},
    {$addFields: {year: '$data_docs.year'}},
    {$addFields: {citing_doi: '$data_docs.citing'}},
    {$project: { 
    		//	_id: false,
                 year: 1,
                 three_type: 1, 
                 citing_doi: 1
                 } 
	},
        {$out:"Question_1"} 
],
    {"allowDiskUse": true }
)

以上大家只需要关注一个点,那就是在使用unwind后一条记录document会变成多个记录document,但是它们的)_id是一样的,众所周知,_id为唯一字段,如果使用out导出来的话使用的还是原来的_id,那样就会报字段重复的错,怎样解决呢,我们可以在$project中添加一句:_id: false,如上图所示,这样使用out后就会自动生成新的_id,避免了重复!

你可能感兴趣的:(mongodb E11000 duplicate key error的几个可能的原因)