如何在Java操作MongoDB时忽略重复的System.UniqueNumber字段值
解决方案
要实现插入时忽略System.UniqueNumber重复的文档,必须从数据库层面约束唯一性+代码层面处理重复插入异常两个步骤入手,具体如下:
1. 创建唯一索引
首先在MongoDB中为System.UniqueNumber字段创建唯一索引,确保数据库层面阻止重复数据写入,这是避免并发场景下重复插入的核心保障。
方式一:MongoDB Shell执行
db.Database.createIndex({"System.UniqueNumber": 1}, {unique: true, background: true})
方式二:Java代码初始化时创建
可以在项目启动或集合初始化时执行一次:
MongoDatabase database = mongoClient.getDatabase("Database"); MongoCollection<Document> collection = database.getCollection("Database"); // 创建唯一索引,background设为true避免阻塞其他操作 collection.createIndex(Indexes.ascending("System.UniqueNumber"), new IndexOptions().unique(true).background(true));
2. 修改Java插入代码
原代码直接用insertMany会在遇到重复数据时抛出异常并终止所有插入,我们改用bulkWrite实现跳过重复文档、继续插入其余有效数据的逻辑:
public boolean create(@Valid @RequestBody Document... documents) { MongoDatabase database = this.mongoClient.getDatabase("Database"); MongoCollection<Document> collection = database.getCollection("Database"); List<InsertOneModel<Document>> insertModels = new ArrayList<>(documents.length); for (Document doc : documents) { // 修正原代码笔误:将booking改为doc Document document = Document.parse(doc.toJson()); insertModels.add(new InsertOneModel<>(document)); } try { // ordered(false)表示遇到错误不中断,继续处理后续文档 BulkWriteResult result = collection.bulkWrite(insertModels, new BulkWriteOptions().ordered(false)); // 可根据业务需求返回结果,比如只要有成功插入就返回true return result.getInsertedCount() > 0; } catch (MongoBulkWriteException e) { // 过滤重复键错误(错误码11000),其他异常正常抛出 boolean hasNonDuplicateError = e.getWriteErrors().stream() .anyMatch(error -> error.getCode() != 11000); if (hasNonDuplicateError) { throw e; } // 仅存在重复键错误时,返回true(表示有效文档已处理) return true; } }
关键说明
- 唯一索引错误码为
11000,捕获MongoBulkWriteException后可通过错误码判断是否为重复数据,跳过此类错误即可。 ordered(false)确保遇到重复文档时,不会中断后续文档的插入操作。- 原代码中存在笔误:
bookings.length应改为documents.length,booking.toJson()应改为doc.toJson(),需修正。
为什么之前的upsert不适用?
upsert的逻辑是存在则更新,不存在则插入,而你的需求是存在则忽略,不存在则插入,两者逻辑不符,因此upsert无法满足需求。
内容的提问来源于stack exchange,提问作者Rose
相关产品推荐
相关产品推荐

