如何解决Mongodb迁移导致密钥重复
在一个旧项目中,我们尝试从基本Spring迁移到Spring Boot 2.3.1。为此,由于我们有mongo数据库,因此必须从编写此代码的spring-data-mongodb:1.10.18迁移:
DBCollection contextCollection = this.mongoTemplate.getCollection("productStock");
BulkWriteOperation builder = contextCollection.initializeUnorderedBulkOperation();
StockType stockItem = stockMessage.getStockItem();
final BasicDBObject id = new BasicDBObject("storeID",stockItem.getStoreID()).append("productID",stockItem.getProductID());
BulkWriteRequestBuilder bulkWriteRequestBuilder = builder.find(new BasicDBObject("_id",id));
HashMap<String,Object> stock = new HashMap<>();
Date currentDate = Calendar.getInstance().getTime();
stock.put("value",stockItem.getValue());
if (stockItem.getAssociateDate() != null) {
stock.put("associateDate",stockItem.getAssociateDate());
}
if (stockItem.getLastAccessDateSource() != null) {
stock.put("lastAccessDateSource",stockItem.getLastAccessDateSource());
// check
BasicDBObject ltLast = new BasicDBObject("$lt",stockItem.getLastAccessDateSource());
BasicDBList dbList = new BasicDBList();
dbList.add(new BasicDBObject(stockItem.getStockCategory() + ".lastAccessDateSource",ltLast));
dbList.add(new BasicDBObject(stockItem.getStockCategory() + ".lastAccessDateSource",null));
bulkWriteRequestBuilder = builder.find(new BasicDBObject("_id",id).append("$or",dbList));
} else {
stock.put("lastAccessDateSource",currentDate);
}
stock.put("lastUpdateDate",currentDate);
BasicDBObject set = new BasicDBObject(stockItem.getStockCategory(),new Document(stock));
bulkWriteRequestBuilder.upsert().updateOne(new BasicDBObject("$set",set));
builder.execute();
使用此更新的代码到spring-data-mongodb:3.0.1.RELEASE
Map<String,List<StockType>> mapMultiUpdate = new HashMap<>();
StockType stockItem = stockMessage.getStockItem();
final Document id = new Document("storeID",stockItem.getProductID());
HashMap<String,Object> stock = new HashMap<>();
Date currentDate = Calendar.getInstance().getTime();
Document searchQuery = new Document("_id",dbList);
stock.put("value",stockItem.getLastAccessDateSource());
// check
Document ltLast = new Document("$lt",stockItem.getLastAccessDateSource());
List<Document> dbList = Lists.newArrayList();
dbList.add(new Document(stockItem.getStockCategory() + ".lastAccessDateSource",ltLast));
dbList.add(new Document(stockItem.getStockCategory() + ".lastAccessDateSource",null));
} else {
stock.put("lastAccessDateSource",currentDate);
}
//Bulk write options
BulkWriteOptions bulkWriteOptions = new BulkWriteOptions();
bulkWriteOptions.ordered(false);
bulkWriteOptions.bypassDocumentValidation(true);
MongoCollection<Document> mongoCollection = this.mongoTemplate.getCollection("productStoreStock");
mongoCollection.bulkWrite(updateDocuments,bulkWriteOptions);
但是当在已经存在的对象上执行新代码时,我们会得到重复的键错误
com.mongodb.MongoBulkWriteException: Bulk write operation error on server localhost:27017. Write errors: [BulkWriteError{index=0,code=11000,message='E11000 duplicate key error collection: test.productStoreStock index: _id_ dup key: { : { storeID: 400,productID: 100000 } }',details={}}].
我们还从mongo-java-driver:3.6.4切换到mongodb-driver-sync:4.0.4
编辑:
在测试阶段的第3步中,在一个空的数据库/集合上抛出此错误。步骤:
- 在特定日期以一种产品的库存开始收集
- 检查基数的值
- 修改Java中股票的价值而不是日期,然后尝试更新
- 由于mongo查询上的LT过滤器,因此仍然是第一个检查值
我们从未达到检查值,并且在迁移之前,此测试的一切都很好
解决方法
test.productStoreStock index: _id_ dup key: { : { storeID: 400,productID: 100000 } }',details={}}
好像您将内部的 id 字段替换为自己的“构造的” ID。这不是一件好事。让mongo创建自己的_id,在使用过程中保证这些都是唯一的。 拥有自己的companyId作为附加字段没什么错,但是替换mongodbs自动生成的_id字段很危险……如您所知。
,Mongo不会更新,如果找不到匹配项,则会进行插入(插入新行)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。