这个问题是我带的徒弟今天遇到的,程序在向mongodb中插入数据时出现id重复的错误,出错的提示如下:
duplicate key error collection: index: id dup key: { : ObjectId(‘68a3c9271f063c20cf82dec9’) }’,
看到这个错误提示你一定会很奇怪id不是自己生成的,怎么会重复呢?要解答这个问题,我们先来看一下ObjectId以及什么是id。
id是集合中文档的主键,用于区分文档,它自动编入索引,并且指定 {id:} 查找是以id索引作为指南的。默认情况下id字段的类型为ObjectId,它是MongoDB的BSON类型之一。如果用户需要还可以将id设置为为ObjectId以外的其他类型。
ObjectId长度为12个字节,由几个2到4字节的链组成。每一个链代表并指定文档身份的具体内容。下面就列出了完整的12个字节组合:
- 4字节的值表示自Unix纪元以来的秒数;
- 3字节的机器标识符;
- 2字节的进程id;
- 3字节的计数器,它以随机值开始。
一般来说,如果文档尚未分配id值,则MongoDB将会自动生成一个id值。我们先来尝试解决一下这个问题,首先我想到的解决方案是这样的:
1.首先我们的代码时批量插入的
Collectwrite.InsertMany(item);
2. 我们把它改成循环,每次只添加一个
foreach(var item in list) { Collectwrite.InsertOne(item); }
但是运行代码还是报错,那么我们在每次田间后都暂停500毫秒呢?
Collectwrite.InsertOne(item); Thread.Sleep(500);
再次运行代码,还是同样的错误。那么这是怎么回事呢?很多情况下id是根据时间戳+主机+进程号+序列生成的,那么重复的原因可能有以下两种:
- 同一时间插入了两条数据,导致了数据库生成了同一个id值;
- 每次使用同一个变量存储不同的数据,进而导致mangodb认为每次存储的是同一条数据,最终生成同一个id值。
这两种原因都有个共同点,那就是让mongodb自己生成id。那么我们可以不让mongodb自己生成id,我们自己手动添加id,当插入的数据带有id的字段时,mongodb就不再自动生成id。至此, mongodb重复id的问题就解决了。解决代码如下:
Collectwrite.DeleteMany(x => x.SeasonId == seasonId); foreach(var item in list) { item.Id = ObjectId.GenerateNewId().ToString(); Collectwrite.InsertOne(item); Thread.Sleep(500); }