MongoDB: insert a record if it does not exist, ignore if it

I have a series of MongoDB entries, for example:

{"name":"Bob", "gpa":4} {"name":"Sarah", "gpa":3}

I will come across various additional entries that may or may not be relevant to the same people. I want to accept them if they are new people, and not update them if they are the people we saw before. Therefore, if I get {"name":"Jim", "gpa":2} , I want to take it as it is. If I get {"name":"Sarah", "gpa":4} (another GPA value), I just want to ignore it. This is not like the logic of either update with "upsert" set to yes, or from findAndModify with "upsert."

https://stackoverflow.com/questions/59610/... offers a method (a unique index in the first field, insert a record, immediately update the second field), but it is several years old, and I wonder now there is no better way to do this in one step.

EDIT:

The accepted answer seems great, but it does not work for me! First, I created an index (this is with the Java driver):

 nameIndex.put("name", 1); nameIndex.put("unique", true); queue.ensureIndex(nameIndex); 

From the command line it is clear that the index exists and is unique. Then the element is inserted:

 DBObject person = new BasicDBObject(); person.put("name", "Bob"); person.put("score", 200000); queue.insert(person); 

Later, the element with the highest scores is reduced to zero:

 BasicDBObject reset = new BasicDBObject(); reset.put("$set", new BasicDBObject("score", 0)); DBObject dbObj = queue.findAndModify(null, new BasicDBObject("score", -1), reset); 

It all works as intended! But, later, the same name can be found again, with a new account. When this last bit of code runs, a new element is created with a different count, which 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'm looking for Bob, I find:

 { "_id" : ObjectId("4f5e865ad6d09315326ea0f0"), "score" : 0, "name" : "Bob" } { "_id" : ObjectId("4f5e8691d6d09315326ea190"), "name" : "Bob", "score" : 886 } 

Created second record with a higher score. Does the field order operate? It seems he should not, and I do not know how to control it.

+7
source share
2 answers

Your call to secureIndex () is not quite right. The first argument to provide Index () contains the keys to be indexed; index parameters (for example, uniqueness) can be passed as a second argument. See Java driver docs .

Now you have an attempt to create an imperfect index in two fields: "name" and "unique".

Try creating your index:

 DBObject nameIndex = new BasicDBObject(); nameIndex.put("name",1); DBObject nameIndexOptions = new BasicDBObject(); nameIndexOptions.put("unique", true); queue.ensureIndex(nameIndex, nameIndexOptions); 
+6
source

The best way to do this would be to set a unique index in the name field using:

 db.foo.ensureIndex({name:1}, {unique:true}); 

This will cause Sarah not to update when you make an insert call because she will find another entry in which β€œSarah” is already set for the name field.

+7
source

All Articles