MongoDB Java 驱动程序:如果文档不存在则插入文档,否则什么也不做

MongoDB Java Driver: Insert document if it does not exist else do nothing

我正在尝试编写一个 Java 函数,将单词列表插入到集合中。我希望每个单词都有一个文档,其中包含唯一字段 "word"。 我要插入的单词列表包含许多重复项,因此我希望我的函数仅在集合中不存在具有相同 "word" 值的文档时才插入文档。如果已经存在具有相同 "word" 值的文档,则该函数不应更改或替换该文档,而是继续从我的列表中插入下一个单词。

我在字段 "word" 上创建了一个索引以避免重复文档并捕获重复键异常,但我不确定这是否是处理此问题的正确方法。

    IndexOptions uniqueWord = new IndexOptions().unique(true);
    collection.createIndex(Indexes.ascending("word"), uniqueWord);


        try {
            File file = new File("src/words.txt");
            Scanner scanner = new Scanner(file);


            while (scanner.hasNextLine()) {
                  String word= scanner.next();

                    Document document = new Document();
                    document.put("word", word);

                    InsertManyOptions unordered= new InsertManyOptions();
                    ArrayList<Document> docs = new ArrayList<>();
                    docs.add(document);

                    try{
                    collection.insertMany(docs, unordered.ordered(false));
                    }catch(Exception e){
                        //System.out.println(e.getMessage());
                    }

您写道:

If there's already a document with the same "word"-value the function should not change or replace this document but go on inserting the next word from my list .

这排除了原子操作的使用,例如 findOneAndUpdatefindOneAndReplaceupsert: true

相反,我认为您的选择仅限于写前检查,例如:

if (collection.count(Filters.eq("word", "..."))) {
    // insert
} else {
    // ignore because there is already a document for this word
}

如果您的编写器是多线程的,这可能会受到竞争条件的影响,例如当一个线程对来自 collection.count() 的错误结果做出反应时,另一个线程设法为该词写入一个条目。 findOneAndReplace 是原子的,所以它不容易出现这个问题,

我建议您应该将 findOneAndReplaceFindOneAndReplaceOptions.upsert == true 一起使用,这与忽略已写入的文档具有相同的最终结果(尽管将其替换为相同的文档) 但它可能比应用预写如果存在检查更安全。

Update 你编辑的问题暗示你是 'inserting many' 但每次循环你只插入一个文档(尽管使用 collection.insertMany())所以以上建议仍然有效。例如:

while (scanner.hasNextLine()) {
    String word= scanner.next();

    if (collection.count(Filters.eq("word", word)) == 0L) {
        Document document = new Document();
        document.put("word", word);

        collection.insertOne(document);
    }
}