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 .
这排除了原子操作的使用,例如 findOneAndUpdate
或 findOneAndReplace
与 upsert: true
。
相反,我认为您的选择仅限于写前检查,例如:
if (collection.count(Filters.eq("word", "..."))) {
// insert
} else {
// ignore because there is already a document for this word
}
如果您的编写器是多线程的,这可能会受到竞争条件的影响,例如当一个线程对来自 collection.count()
的错误结果做出反应时,另一个线程设法为该词写入一个条目。 findOneAndReplace
是原子的,所以它不容易出现这个问题,
我建议您应该将 findOneAndReplace
与 FindOneAndReplaceOptions.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);
}
}
我正在尝试编写一个 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 .
这排除了原子操作的使用,例如 findOneAndUpdate
或 findOneAndReplace
与 upsert: true
。
相反,我认为您的选择仅限于写前检查,例如:
if (collection.count(Filters.eq("word", "..."))) {
// insert
} else {
// ignore because there is already a document for this word
}
如果您的编写器是多线程的,这可能会受到竞争条件的影响,例如当一个线程对来自 collection.count()
的错误结果做出反应时,另一个线程设法为该词写入一个条目。 findOneAndReplace
是原子的,所以它不容易出现这个问题,
我建议您应该将 findOneAndReplace
与 FindOneAndReplaceOptions.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);
}
}