MongoDB:使用唯一索引进行upsert

时间:2015-10-14 12:15:26

标签: java mongodb upsert

我必须说我不是真正的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重复”   关键错误索引

我不想删除唯一索引,因为可能存在重复的食物对象。我该如何解决这个问题?

1 个答案:

答案 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
    }