【问题标题】:MongoDB Java: how to get write error document?MongoDB Java:如何获取写入错误文档?
【发布时间】:2018-02-27 08:30:23
【问题描述】:

我通过 mongodb java api 3.6.1 和方法 insertMany(List<Document>) 使用无序批量一次在 mongodb 3.6 中插入 1000 个文档。

try {
    collection.insertMany(docs);
} catch (MongoBulkWriteException e) {
    // e is :
   // Bulk write operation error on server myserver.com:27011. Write errors: [BulkWriteError{index=0, code=11000, message='E11000 duplicate key error collection: foodb.bar index: bar.id_1 dup key: { : 1 }', details={ }}].     
}

假设只有一个文档触发了重复键错误。其他 999 个文档均已成功插入。
如何知道是哪个文档触发了错误?

当然,当出现重复键错误时,我可以使用重复的 bar.id 搜索我的文档列表,但这很不方便(这意味着解析 WriteError 消息......)如果有两个文档具有相同的bar.idList<Document> 中,不询问数据库几乎不可能知道是哪个触发了错误。

谢谢

【问题讨论】:

标签: java mongodb bulkinsert mongodb-java


【解决方案1】:

MongoBulkWriteException 包含一个List<BulkWriteError>,每个失败的写入都将由该列表中的一个元素表示。此列表中的每个元素都包含一个 index 属性,该属性填充了所提供文档列表中元素的索引。

因此,您可以使用此index 来确定哪些提供的文档失败了。

这里有一个测试用例展示了这一点:

@Test
public void canBulkWriteAndIdentifySpecificFailedDocuments() throws IOException {
    MongoClient mongoClient = new MongoClientFactory().create();

    MongoCollection<Document> collection = mongoClient.getDatabase("stackoverflow").getCollection("bulkwrite");

    // fresh start for this test case
    collection.drop();

    Document knownDocument = new Document().append("name", new BsonString("beep"));
    collection.insertOne(knownDocument);

    collection.createIndex(new BasicDBObject("name", 1), new IndexOptions().unique(true));

    int createDuplicateOnIndex = 2;
    List<Document> docs = Lists.newArrayList();
    for (int i = 0; i < 5; i++) {
        if (i == createDuplicateOnIndex) {
            // deliberately trigger a duplicate key exception
            docs.add(knownDocument);
        } else {
            docs.add(new Document().append("name", new BsonString("beep" + i)));
        }
    }

    try {
        collection.insertMany(docs, new InsertManyOptions().ordered(false));
    } catch (MongoBulkWriteException ex) {
        assertThat(ex.getWriteResult().getInsertedCount(), is(4));
        assertThat(ex.getMessage(), containsString("duplicate key error"));
        assertThat(ex.getWriteErrors().size(), is(1));
        assertThat(ex.getWriteErrors().get(0).getIndex(), is(createDuplicateOnIndex));
        assertThat(ex.getWriteErrors().get(0).getCode(), is(11000));
        assertThat(ex.getWriteErrors().get(0).getMessage(), startsWith("E11000 duplicate key error"));
    }
}

在这个测试用例中我们...

  1. 编写文档
  2. 在目标集合上创建唯一索引
  3. 写入一组文档(使用 new InsertManyOptions().ordered(false) 进行无序写入),其中一个违反了唯一索引
  4. 断言批量插入导致抛出MongoBulkWriteException,并且此异常报告 4 次成功写入和 1 次失败写入,E11000 duplicate key error 和一个索引值清楚地表明此失败与第三个文档(@ 987654329@) 在给定的列表中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-11
    相关资源
    最近更新 更多