Java MongoDB:如果不存在则插入记录,如果存在则忽略
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9660851/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
MongoDB: insert record if it doesn't exist, ignore if it does
提问by umbraphile
I have a series of MongoDB records like:
我有一系列 MongoDB 记录,例如:
{"name":"Bob", "gpa":4}
{"name":"Sarah", "gpa":3}
{"name":"Bob", "gpa":4}
{"name":"Sarah", "gpa":3}
I will encounter various additional records that may or may not pertain to the same people. I want to accept them if they're new people, and notupdate them if they're people we've seen before. So if I get {"name":"Jim", "gpa":2}
, I want to accept that as-is. If I get {"name":"Sarah", "gpa":4}
(different GPA value), I want to just ignore it. This doesn't seem to be the logic of either update
with "upsert" set to yes, or of findAndModify
with "upsert."
我会遇到各种额外的记录,这些记录可能属于也可能不属于同一个人。我想接受他们,如果他们是新人,而不是如果他们是人,我们以前看到更新。所以如果我得到{"name":"Jim", "gpa":2}
,我想按原样接受。如果我得到{"name":"Sarah", "gpa":4}
(不同的 GPA 值),我只想忽略它。这似乎不是update
“upsert”设置为yes或“upsert”的逻辑findAndModify
。
https://stackoverflow.com/a/3260290/514757suggests a way (unique index on the first field, insert record, immediately update the second field) but it's a few years old and I wonder if there isn't a better way now to do this in a single step.
https://stackoverflow.com/a/3260290/514757提出了一种方法(第一个字段上的唯一索引,插入记录,立即更新第二个字段)但它已经有几年了,我想知道是否有更好的方法现在只需一步即可完成此操作。
EDIT:
编辑:
The accepted answer seems great, but it's not working for me! First, I created the index (this is with the Java driver):
接受的答案似乎很好,但对我不起作用!首先,我创建了索引(这是使用 Java 驱动程序):
nameIndex.put("name", 1);
nameIndex.put("unique", true);
queue.ensureIndex(nameIndex);
I can see from the command line that the index exists and is unique. Then, an item is inserted:
我可以从命令行看到索引存在并且是唯一的。然后,插入一个项目:
DBObject person = new BasicDBObject();
person.put("name", "Bob");
person.put("score", 200000);
queue.insert(person);
Later, the item with the highest score has its score reduced to zero:
之后,得分最高的项目的得分降为零:
BasicDBObject reset = new BasicDBObject();
reset.put("$set", new BasicDBObject("score", 0));
DBObject dbObj = queue.findAndModify(null, new BasicDBObject("score", -1), reset);
All of this works just as intended! But, later, the same name may be found again, with a new score. When this last bit of code runs, a new item is created with a different score, which is exactly what I don't want:
所有这些都按预期工作!但是,稍后,可能会再次找到相同的名称,并带有新的分数。当最后一段代码运行时,会创建一个具有不同分数的新项目,这正是我不想要的:
BasicDBObject queueable = new BasicDBObject();
queueable.put("name", "Could be Bob again, could be someone new");
queueable.put("score", 1234);
queue.insert(queueable);
If I search for Bob, I find:
如果我搜索 Bob,我会发现:
{ "_id" : ObjectId("4f5e865ad6d09315326ea0f0"), "score" : 0, "name" : "Bob" }
{ "_id" : ObjectId("4f5e8691d6d09315326ea190"), "name" : "Bob", "score" : 886 }
A second record has been created, with the higher score again. Does the order of the fields matter? It doesn't seem like it should, and I don't know how to control that.
创造了第二个记录,再次获得更高的分数。字段的顺序重要吗?似乎不应该,我不知道如何控制。
采纳答案by Trip Volpe
Your ensureIndex() call is not quite right. The first argument to ensureIndex() contains the keys that should be indexed; index options (like uniqueness) can be passed as the second argument. See the Java driver docs.
您的 ensureIndex() 调用不太正确。ensureIndex() 的第一个参数包含应该被索引的键;索引选项(如唯一性)可以作为第二个参数传递。请参阅Java 驱动程序文档。
What you've got right now is attempting to create a non-unique index on two fields: "name" and "unique".
您现在所拥有的是尝试在两个字段上创建非唯一索引:“名称”和“唯一”。
Try this to create your index:
试试这个来创建你的索引:
DBObject nameIndex = new BasicDBObject();
nameIndex.put("name",1);
DBObject nameIndexOptions = new BasicDBObject();
nameIndexOptions.put("unique", true);
queue.ensureIndex(nameIndex, nameIndexOptions);
回答by Fapiko
The best way to accomplish this would be to set a unique index on the name field using:
完成此操作的最佳方法是使用以下方法在 name 字段上设置唯一索引:
db.foo.ensureIndex({name:1}, {unique:true});
This will cause Sarah to not get updated when you make an insert call because it will find another record where 'Sarah' is already set for the name field.
这将导致 Sarah 在您进行插入调用时不会得到更新,因为它会找到另一条记录,其中已为 name 字段设置了“Sarah”。