[JAVA-3137] findOneAndUpdate with empty update will clear the document Created: 10/Jan/19  Updated: 19/Aug/19  Resolved: 19/Aug/19

Status: Closed
Project: Java Driver
Component/s: Command Operations, Query Operations
Affects Version/s: 3.9.1
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Siqi Li Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Java 8, Windows 10, Mongo Java Driver 3.9.1, Mongo 3.4


Issue Links:
Duplicate
duplicates JAVA-3369 findOneAndUpdate does not handle an e... Closed
Related
related to JAVA-3369 findOneAndUpdate does not handle an e... Closed

 Description   

Here's my example code:

import org.bson.Document;
 
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.ReturnDocument;
 
public class MongoFindOneAndUpdateTest {
 
	public static void main(String[] args) {
		// I'm running mongo 3.4 locally
		final String connStr = "mongodb://localhost:27017/test?ssl=false";
		final MongoCollection<Document> col = MongoClients.create(connStr)
				.getDatabase("test").getCollection("fakeCol");
		// Make sure we start with an empty collection
		col.drop();
		// insert a simple document
		col.insertOne(new Document()
				.append("_id", "fakeId")
				.append("one", 1)
				.append("foo", "bar"));
		{
			final Document doc = col.find().iterator().next();
			System.out.println(doc.toJson());
			// prints { "_id" : "fakeId", "one" : 1, "foo" : "bar" } as expected
		}
		{
			// Find a document with no filter and update it with no operation,
			// and then return the updated document, at least that's what I expected to happen.
			final Document doc = col.findOneAndUpdate(new Document(), new Document(),
					new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER));
			System.out.println(doc.toJson());
			// prints { "_id" : "fakeId" }
			// What???
		}
		{
			// Just to be sure the previous result is correct
			final Document doc = col.find().iterator().next();
			System.out.println(doc.toJson());
			// prints { "_id" : "fakeId" }
			// Yeah, the document was for some reason obliterated
		}
		col.drop();
	}
 
}

 

So basically if I do findOneAndUpdate with an empty Document, then it will clear out every field on the document found apart from _id.

 

I tried the same thing in Mongo shell, and doing db.fakeCol.findOneAndUpdate({}, {}) is not even allowed. It says "the update operation document must contain at least one atomic operator".

 



 Comments   
Comment by Jeffrey Yemin [ 16/Jan/19 ]

This should wait until 4.0, when we can safely add default methods to the FieldNameValidator interface, something like:

 
    // start validation of a single document
 
    void start() {}
 
    // end validation of a single document, possibly returning false to indicate a validation failure.
 
    boolean end() {}

Comment by Jeffrey Yemin [ 10/Jan/19 ]

We'll have to pre-serialize the update document to check if it's empty, as the existing validation framework that we have in BsonWriter is not sufficient to check for a condition like this. That validator will find incorrect usage like{{ col.findOneAndUpdate(new Document(), new Document("x", 1))}}, though with a pretty unhelpful error message:

Exception in thread "main" java.lang.IllegalArgumentException: Invalid BSON field name x

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