[JAVA-642] Using findAndModify to do a "getOrCreate" Created: 13/Sep/12  Updated: 11/Sep/19  Resolved: 13/Sep/12

Status: Closed
Project: Java Driver
Component/s: API
Affects Version/s: 2.8.0
Fix Version/s: None

Type: Task Priority: Minor - P4
Reporter: Michael Champagne Assignee: Unassigned
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Windows



 Description   

I would like to use findAndModify to get one document, without doing any modification on it. My need is to find a single document in a collection, or create it if it doesn't exist.

Here's my java code (based on http://api.mongodb.org/java/2.8.0/) and the error I get.

java

MyDocument doc = (MyDocument) myCollection.findAndModify(query, null, null, false, null, true, true);
 
com.mongodb.CommandResult$CommandFailure: command failed [findandmodify]: { "serverUsed" : "serverDns/ip:port" , "errmsg" : "need remove or update" , "ok" : 0.0}

Now let's take a look at the parameters :
query - query to match
fields - fields to be returned
sort - sort to apply before picking first document
remove - if true, document found will be removed
update - update to apply
returnNew - if true, the updated document is returned, otherwise the old document is returned (or it would be lost forever)
upsert - do upsert (insert if document not present)

I have 2 servers that might access this database, so that's why I need an atomic-like "getOrCreate" behavior. There might be a better way of doing this.



 Comments   
Comment by Michael Champagne [ 14/Sep/12 ]

Didn't know that we can't update the _id field of a document.
Well, i will try this :

  • have a mongoId and sqlId fields in my SQL table,
  • let mongo set the _id of my documents,
  • put that mongoId in my sql table, as well as a sqldId field,
  • use the mongoId when "joining" mongo data with sql data,
  • use the sqlId when joining in sql only.

I know this isn't the better implementation, but it's temporary until I turn all sql tables into mongo collections. I'm pretty sure it will work for my needs for now.

Comment by Jeffrey Yemin [ 14/Sep/12 ]

I don't see a way around this. The _id field is immutable once the document is created, and mongo will not generate _id's other than ObjectId's Can you store the ObjectId as a binary field in your SQL database?

Comment by Michael Champagne [ 14/Sep/12 ]

I have another problem with findAndModify. I don't use the ID in my query, thus when the document isn't found, it is created with a mongo generated id.

I don't want to use mongo generated ids because I need a numeric value (to put in the column of a SQL table).

In my java application, I am generating an ID (which is a long) and I would like the document to have that ID when not found when using findAndModify. If I can't do that, I will have to do an update after findAndModify and that will be a problem when 2 servers will run that code at the same time. The first will create the document with a mongo id, then the other might get the document with that wrong id before the first server updates it.

Comment by Jeffrey Yemin [ 14/Sep/12 ]

Yeah, it's not the most intuitive API.

Comment by Michael Champagne [ 14/Sep/12 ]

Thank you, it works!
I had tried null and new BasicDBObject() without success... I just didn't know how to make my command update nothing. An empty $set command does just that

Comment by Jeffrey Yemin [ 13/Sep/12 ]

It's because you're passing null to the update argument (3rd from the end). Try something like:

MyDocument doc = (MyDocument) myCollection.findAndModify(query, null, null, false, new BasicDBObject("$set", new BasicDBObject()), true, true);

Generated at Thu Feb 08 08:52:45 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.