我必须说我不是真正的mongoDB专家,但这正是我想要做的。
我有一个应用程序,每次打开应用程序时都会获得“食物”对象的提要,此提要是从外部Web API服务接收的。由于ToS与外部API服务协议,我只能为每个对象保存唯一“食物”ID。
现在,每次打开应用程序时,我都会获得食物对象的提要,我只想在我的mongoDB中保存食物对象ID(“foodId”)一次。因此,每次打开应用程序时,我都决定做一个upsert。我不确定这是否是编写upsert方法的最佳方法,因为您可以看到查询参数和更新参数相同且都与“foodId”相关:
Query query = new Query();
query.addCriteria(Criteria.where("foodId").in(foodIdfromApi));
Update update = new Update();
update.set("foodId", foodIdfromApi);
mongoTemplate.upsert(query, update, Food.class);
由于“foodId”是独一无二的,我在“foodId”上创建了一个独特的索引
这是来自MongoDB: http://docs.mongodb.org/manual/reference/method/db.collection.update/#upsert-option
为防止MongoDB多次插入同一文档, 在名称字段上创建唯一索引。如果有唯一索引 多个应用程序使用upsert发出相同的更新:true,完全正确 一个update()将成功插入一个新文档。
剩下的操作可以是:
更新新插入的文档,或在尝试时失败 插入副本。如果操作由于重复而失败 索引键错误,应用程序可能会重试该操作 成功作为更新操作。
我的应用首次成功下载Feed。但随后,每当我想要进行upsert时(每次我打开我的应用程序),它都会给我重复的索引键错误。
写入失败,错误代码为11000,错误消息为“E11000重复” 关键错误索引
我不想删除唯一索引,因为可能存在重复的食物对象。我该如何解决这个问题?
答案 0 :(得分:1)
您没有删除唯一索引。正如你在文档中指出的那样,在mongo中这是必要的。
如果在尝试upsert时出现问题,要解决他们的选择以抛出错误,您应该捕获错误并重试。
我没有使用mongo模板,但这是使用Java驱动程序的示例。您可以尝试类似的东西:
MongoCollection<Document> collection = mongo.getCollection("Revenue");
UpdateResult result;
try {
result = collection.replaceOne(searchDoc, repsertDoc, new UpdateOptions().upsert(true));
} catch (MongoException e) {
// Retry once on error, can sleep here too if you'd like
result = collection.replaceOne(searchDoc, repsertDoc, new UpdateOptions().upsert(true));
// If this attempt fails, can always re-try again or fail
}